【问题标题】:MySql query with left join and Inner Join on the result带有左连接和内连接的 MySql 查询结果
【发布时间】:2014-02-06 09:23:00
【问题描述】:

我在 MySql 中有两个表,一个是 users,第二个是 users 交易,交易通过 user.id = transaction.user_id 与用户相关 并非所有用户都有交易,每个用户的交易没有限制 所有交易都添加了_date字段

我需要的是一个查询,它将为我提供所有用户的列表,其中包含关于他们最后添加的交易(最后一个交易)的数据,或者如果他们没有任何交易,则为 null

所以我的想法是

获取所有用户 在 user.id = transaction.user_id 上留下加入交易 内部连接以获取按 id 分组的 max transaction. added_date

类似:

SELECT u.id, 
       u.name, 
       t.added_date
  FROM `user` u 
                LEFT JOIN `transaction` t 
                          ON u.id = t.user_id
               INNER JOIN (
                           SELECT id, 
                                  MAX(added_date) AS addedDate
                             FROM `transaction`
                         GROUP BY id
                           )gt
                          ON t.id = gt.id AND t.added_date = gt.addedDate

但它给我的结果不是我所期望的,它把交易留给了用户,但我在结果集中仍然有很多同一个用户的交易

我做错了什么?

编辑:

我稍微简化了它们,但这应该足够了:

用户

CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(256) NOT NULL,
`email` varchar(128) NOT NULL,
`role_id` mediumint(8) unsigned NOT NULL,
`phone` varchar(128) NOT NULL, 
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

交易

    CREATE TABLE `transaction` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned DEFAULT NULL,  
  `added_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
  PRIMARY KEY (`id`),
  KEY `fk_transaction_user1_idx` (`user_id`),
  CONSTRAINT `transaction_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)     ON DELETE CASCADE ON UPDATE CASCADE
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我需要所有用户的列表以及他们最后的交易数据,如果没有,则为空

【问题讨论】:

  • 如果将ON t.id = gt.id AND t.added_date = gt.addedDate 替换为ON (t.id = gt.id AND t.added_date = gt.addedDate) 会发生什么?
  • 我已按照您的建议添加了括号,结果看起来相同
  • 我已经编辑了我的帖子,提供了简化的 CREATE

标签: mysql sql join


【解决方案1】:

你这个

  SELECT user.name, MAX(transaction.added_date) 
    FROM user 
              LEFT JOIN transaction 
                         ON user.id = transaction.user_id
GROUP BY user.name;

Here is SQL Fiddle

另外,尽量避免使用有利于JOINs、because the subqueries usually not good on perfomance的子查询

UPD. SQL Fiddle, with sorting ASC by date and NULLs last,使用COALESCE
UPD2. Another SQL Fiddle with count

【讨论】:

  • Rakesh 感谢您的回答,但在标准的 1000 行限制下,执行时间超过 35 秒并获取另外 25 秒,因此远远超过了可接受的性能
  • Alexander 效果很好 我真的很惊讶它如此简单,我会仔细检查结果是否正确并投票赞成。还有一件事,当 ORDER BY ASC 时,将空值踢到结果列表底部的最佳方法是什么?
  • 这样吗?当 MyDate 为 null 然后 1 else 0 end, MyDate 时按大小写
  • 不,你看,我想通过 added_date byt ASC 对结果进行排序,首先生成空值,我希望它们位于最后,而不是像普通 ASC 中那样 null、null、null、1、 2,3 我需要将它们排序为 1,2,3,null,null,null(null 表示没有加入事务的用户记录)
  • 100%,很高兴有你在这里,亚历山大,非常感谢!我投票赞成你的回答
【解决方案2】:

请试试这个

SELECT u.id, 
       u.name, 
       t.added_date 
  FROM `users` u 
       LEFT JOIN `transaction` t 
                 ON u.id = t.user_id AND t.added_date = (
                                         SELECT MAX( added_date ) 
                                           FROM `transaction` t 
                                          WHERE t.user_id = u.id
                                         )

【讨论】:

    猜你喜欢
    • 2019-05-24
    • 1970-01-01
    • 2021-09-25
    • 2012-04-10
    • 2012-08-08
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多