MySQL INNER JOIN只从第二个表中select一行
我有一个users
表和payments
表,为每个用户,其中有付款,可能有多个关联付款的payments
表。 我想select所有有付款的用户,但只select他们的最新付款。 我正在尝试这个SQL,但我从来没有尝试嵌套的SQL语句之前,所以我想知道我做错了什么。 感谢帮助
SELECT u.* FROM users AS u INNER JOIN ( SELECT p.* FROM payments AS p ORDER BY date DESC LIMIT 1 ) ON p.user_id = u.id WHERE u.package = 1
您需要有一个子查询来获取每个user ID
的最新date。
SELECT a.*, c.* FROM users a INNER JOIN payments c ON a.id = c.user_ID INNER JOIN ( SELECT user_ID, MAX(date) maxDate FROM payments GROUP BY user_ID ) b ON c.user_ID = b.user_ID AND c.date = b.maxDate WHERE a.package = 1
SELECT u.*, p.*, max(p.date) FROM payments p JOIN users u ON u.id=p.user_id AND u.package = 1 GROUP BY u.id ORDER BY p.date DESC
看看这个sqlfiddle
您的查询有两个问题:
- 每个表和子查询都需要一个名称,所以你必须命名子查询
INNER JOIN (SELECT ...) AS p ON ...
- 子查询只有返回一个行的时间段,但实际上每个用户需要一行。 为此,您需要一个查询来获取最大date,然后自回来获取整个行。
假设payment.date没有关系,请尝试:
SELECT u.*, p.* FROM ( SELECT MAX(p.date) AS date, p.user_id FROM payments AS p GROUP BY p.user_id ) AS latestP INNER JOIN users AS u ON latestP.user_id = u.id INNER JOIN payments AS p ON p.user_id = u.id AND p.date = latestP.date WHERE u.package = 1
SELECT u.* FROM users AS u INNER JOIN ( SELECT p.*, @num := if(@id = user_id, @num + 1, 1) as row_number, @id := user_id as tmp FROM payments AS p, (SELECT @num := 0) x, (SELECT @id := 0) y ORDER BY p.user_id ASC, date DESC) ON (p.user_id = u.id) and (p.row_number=1) WHERE u.package = 1
Matei Mihai给出了一个简单而有效的解决scheme,但是直到在SELECT部分放置一个MAX(date)
才会工作,所以这个查询将变成:
SELECT u.*, p.*, max(date) FROM payments p JOIN users u ON u.id=p.user_id AND u.package = 1 GROUP BY u.id
而按顺序将不会有任何分组,但它可以命令由组提供的最终结果。 我试了一下,它为我工作。
@John Woo的回答帮助我解决了一个类似的问题。 我通过设置正确的顺序来改进他的答案。 这对我有效:
SELECT a.*, c.* FROM users a INNER JOIN payments c ON a.id = c.user_ID INNER JOIN ( SELECT user_ID, MAX(date) as maxDate FROM ( SELECT user_ID, date FROM payments ORDER BY date DESC ) d GROUP BY user_ID ) b ON c.user_ID = b.user_ID AND c.date = b.maxDate WHERE a.package = 1
不过,我不确定这个效率如何。