MySQL INNER JOIN只从第二个表中选择一行

时间:2012-09-21 07:40:38

标签: mysql sql select inner-join

我有一个users表和一个payments表,对于每个有付款的用户,可能在payments表中有多个关联付款。我想选择所有付款用户,但只选择最新付款。我正在尝试这个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

11 个答案:

答案 0 :(得分:110)

您需要有一个子查询才能获得user ID的最新日期。

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

答案 1 :(得分:10)

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

答案 2 :(得分:7)

SELECT u.*, p.*
FROM users AS u
INNER JOIN payments AS p ON p.id = (
    SELECT id
    FROM payments AS p2
    WHERE p2.user_id = u.id
    ORDER BY date DESC
    LIMIT 1
)

此解决方案比accepted answer更好,因为当某些付款使用相同的用户和日期时,它可以正常工作。

答案 3 :(得分:3)

   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

答案 4 :(得分:2)

SELECT U.*, V.* FROM users AS U 
INNER JOIN (SELECT *
FROM payments
WHERE id IN (
SELECT MAX(id)
FROM payments
GROUP BY user_id
)) AS V ON U.id = V.user_id

这将使其正常工作

答案 5 :(得分:1)

您的查询存在两个问题:

  1. 每个表和子查询都需要一个名称,因此您必须为子查询命名INNER JOIN (SELECT ...) AS p ON ...
  2. 您拥有的子查询只返回一个行周期,但实际上您需要为每个用户创建一行。为此,您需要一个查询来获取最大日期,然后自我加入以获得整行。
  3. 假设payments.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
    

答案 6 :(得分:1)

Matei Mihai给出了一个简单而有效的解决方案但是在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

顺序不会对分组产生任何影响,但它可以命令分组提供的最终结果。我试过了,它对我有用。

答案 7 :(得分:1)

@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

我不确定这是多么有效率。

答案 8 :(得分:0)

如果在ORDER BY子句中需要多个cols,我的答案直接受到@valex的启发非常有用。

    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 (SELECT * FROM payments ORDER BY p.user_id ASC, date DESC) AS p,
             (SELECT @num := 0) x,
             (SELECT @id := 0) y
        )
    ON (p.user_id = u.id) and (p.row_number=1)
    WHERE u.package = 1

答案 9 :(得分:0)

您可以尝试以下方法:

SELECT u.*, p.*
FROM users AS u LEFT JOIN (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY userid ORDER BY [Date] DESC) AS RowNo
    FROM payments  
) AS p ON u.userid = p.userid AND p.RowNo=1

答案 10 :(得分:0)

这很简单:假设您的表是用户,并且付款查询可以是

,那么先进行内部联接,然后按user_id分组,并在payment_id中使用max汇总函数。

select user.id, max(payment.id) from user inner join payment on (user.id = payment.user_id) group by user.id