代码之家  ›  专栏  ›  技术社区  ›  bcmcfc

MySQL是否只加入最近一行?

  •  69
  • bcmcfc  · 技术社区  · 15 年前

    我有一个表customer,它存储客户id、电子邮件和参考资料。另外还有一个表customer\u data,它存储了对客户所做更改的历史记录,即当发生更改时,插入一个新行。

    为了在表中显示客户信息,需要将两个表连接起来,但是只有customer\数据中最新的一行应该连接到customer表。

    如何使用MySQL实现这一点?我想我想在那里的某个地方放一个独特的。。。

    SELECT *, CONCAT(title,' ',forename,' ',surname) AS name
    FROM customer c
    INNER JOIN customer_data d on c.customer_id=d.customer_id
    WHERE name LIKE '%Smith%' LIMIT 10, 20
    

    另外,我认为我可以这样用CONCAT和LIKE吗?

    (我知道内部连接可能是错误的连接类型。实际上我不知道不同连接之间有什么区别。我现在要调查一下!)

    9 回复  |  直到 6 年前
        1
  •  163
  •   Daniel Vassallo    15 年前

    您可以尝试以下操作:

    SELECT    CONCAT(title, ' ', forename, ' ', surname) AS name
    FROM      customer c
    JOIN      (
                  SELECT    MAX(id) max_id, customer_id 
                  FROM      customer_data 
                  GROUP BY  customer_id
              ) c_max ON (c_max.customer_id = c.customer_id)
    JOIN      customer_data cd ON (cd.id = c_max.max_id)
    WHERE     CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%' 
    LIMIT     10, 20;
    

    JOIN 只是 INNER JOIN .

    CREATE TABLE customer (customer_id int);
    CREATE TABLE customer_data (
       id int, 
       customer_id int, 
       title varchar(10),
       forename varchar(10),
       surname varchar(10)
    );
    
    INSERT INTO customer VALUES (1);
    INSERT INTO customer VALUES (2);
    INSERT INTO customer VALUES (3);
    
    INSERT INTO customer_data VALUES (1, 1, 'Mr', 'Bobby', 'Smith');
    INSERT INTO customer_data VALUES (2, 1, 'Mr', 'Bob', 'Smith');
    INSERT INTO customer_data VALUES (3, 2, 'Mr', 'Jane', 'Green');
    INSERT INTO customer_data VALUES (4, 2, 'Miss', 'Jane', 'Green');
    INSERT INTO customer_data VALUES (5, 3, 'Dr', 'Jack', 'Black');
    

    结果(不带 LIMIT WHERE ):

    SELECT    CONCAT(title, ' ', forename, ' ', surname) AS name
    FROM      customer c
    JOIN      (
                  SELECT    MAX(id) max_id, customer_id 
                  FROM      customer_data 
                  GROUP BY  customer_id
              ) c_max ON (c_max.customer_id = c.customer_id)
    JOIN      customer_data cd ON (cd.id = c_max.max_id);
    
    +-----------------+
    | name            |
    +-----------------+
    | Mr Bob Smith    |
    | Miss Jane Green |
    | Dr Jack Black   |
    +-----------------+
    3 rows in set (0.00 sec)
    
        2
  •  124
  •   Chololoco    8 年前

    SELECT c.*,
    FROM client AS c
    LEFT JOIN client_calling_history AS cch ON cch.client_id = c.client_id
    WHERE
       cch.cchid = (
          SELECT MAX(cchid)
          FROM client_calling_history
          WHERE client_id = c.client_id AND cal_event_id = c.cal_event_id
       )
    
        3
  •  10
  •   John Magnolia Mozammil    7 年前

    假定中的自动增量列 customer_data 被命名为 Id ,您可以执行以下操作:

    SELECT CONCAT(title,' ',forename,' ',surname) AS name *
    FROM customer c
        INNER JOIN customer_data d 
            ON c.customer_id=d.customer_id
    WHERE name LIKE '%Smith%'
        AND d.ID = (
                    Select Max(D2.Id)
                    From customer_data As D2
                    Where D2.customer_id = D.customer_id
                    )
    LIMIT 10, 20
    
        4
  •  9
  •   payne8    11 年前

    对于任何必须使用较旧版本MySQL(5.0之前的版本)的用户,您不能对这种类型的查询执行子查询。这是我能做的解决方案,看起来效果很好。

    SELECT MAX(d.id), d2.*, CONCAT(title,' ',forename,' ',surname) AS name
    FROM customer AS c 
    LEFT JOIN customer_data as d ON c.customer_id=d.customer_id 
    LEFT JOIN customer_data as d2 ON d.id=d2.id
    WHERE CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%'
    GROUP BY c.customer_id LIMIT 10, 20;
    

    本质上,这是查找数据表的max id,将其连接到客户,然后将数据表连接到找到的max id。这是因为选择组的最大值并不能保证其余数据与id匹配,除非您将其重新连接到自身。

    我还没有在MySQL的新版本上测试过这个,但是它可以在4.0.30上运行。

        5
  •  7
  •   BenMorel Manish Pradhan    7 年前

    我知道这个问题由来已久,但多年来一直备受关注,我认为它缺少了一个可能对类似案件中的人有所帮助的概念。我把它加在这里是为了完整。

    如果你 可以 ,但是,如果要修改您的模式,我建议您在 customer id 最新的 customer_data 此客户的记录:

    CREATE TABLE customer (
      id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
      current_data_id INT UNSIGNED NULL DEFAULT NULL
    );
    
    CREATE TABLE customer_data (
       id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
       customer_id INT UNSIGNED NOT NULL, 
       title VARCHAR(10) NOT NULL,
       forename VARCHAR(10) NOT NULL,
       surname VARCHAR(10) NOT NULL
    );
    

    查询客户

    SELECT c.*, d.title, d.forename, d.surname
    FROM customer c
    INNER JOIN customer_data d on d.id = c.current_data_id
    WHERE ...;
    

    缺点是在创建或更新客户时会有额外的复杂性。

    更新客户

    表,并更新 顾客 记录。

    INSERT INTO customer_data (customer_id, title, forename, surname) VALUES(2, 'Mr', 'John', 'Smith');
    UPDATE customer SET current_data_id = LAST_INSERT_ID() WHERE id = 2;
    

    创建客户

    创建客户只是插入 顾客 输入,然后运行相同的语句:

    INSERT INTO customer () VALUES ();
    
    SET @customer_id = LAST_INSERT_ID();
    INSERT INTO customer_data (customer_id, title, forename, surname) VALUES(@customer_id, 'Mr', 'John', 'Smith');
    UPDATE customer SET current_data_id = LAST_INSERT_ID() WHERE id = @customer_id;
    

    创建/更新客户的额外复杂性可能令人恐惧,但可以通过触发器轻松实现自动化。

    Customer 模型看起来像:

    class Customer
    {
        private int id;
        private CustomerData currentData;
    
        public Customer(String title, String forename, String surname)
        {
            this.update(title, forename, surname);
        }
    
        public void update(String title, String forename, String surname)
        {
            this.currentData = new CustomerData(this, title, forename, surname);
        }
    
        public String getTitle()
        {
            return this.currentData.getTitle();
        }
    
        public String getForename()
        {
            return this.currentData.getForename();
        }
    
        public String getSurname()
        {
            return this.currentData.getSurname();
        }
    }
    

    你的永恒 CustomerData 仅包含getter的模型:

    class CustomerData
    {
        private int id;
        private Customer customer;
        private String title;
        private String forename;
        private String surname;
    
        public CustomerData(Customer customer, String title, String forename, String surname)
        {
            this.customer = customer;
            this.title    = title;
            this.forename = forename;
            this.surname  = surname;
        }
    
        public String getTitle()
        {
            return this.title;
        }
    
        public String getForename()
        {
            return this.forename;
        }
    
        public String getSurname()
        {
            return this.surname;
        }
    }
    
        6
  •  2
  •   Pramendra Gupta    15 年前
    SELECT CONCAT(title,' ',forename,' ',surname) AS name * FROM customer c 
    INNER JOIN customer_data d on c.id=d.customer_id WHERE name LIKE '%Smith%' 
    

    c、 客户id到c.id

    else更新表结构

        7
  •  1
  •   alexandre-rousseau Jelle de Fries    7 年前

    你也可以这样做

    SELECT    CONCAT(title, ' ', forename, ' ', surname) AS name
    FROM      customer c
    LEFT JOIN  (
                  SELECT * FROM  customer_data ORDER BY id DESC
              ) customer_data ON (customer_data.customer_id = c.customer_id)
    GROUP BY  c.customer_id          
    WHERE     CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%' 
    LIMIT     10, 20;
    
        8
  •  0
  •   Burcin    15 年前

    将实际数据记录到 客户数据