从每个"组中选择一个"

时间:2014-09-12 22:38:47

标签: mysql sql mysql-workbench

如果我运行以下MySQL命令:

SELECT * FROM mail f where f.toUserId = 15 AND f.toUserDeleted=0 ORDER BY f.sentDate DESC limit 0,100000

我会按正确顺序收到所有邮件,我可以清楚地看到最后发送的最后一条邮件。

但是,我确实需要将此搜索命名为:

SELECT 
   f.id, 
   f.fromUserId, 
   f.fromUserNickName, 
   f.readDate, 
   f.sentDate, 
   f.subject, 
   f.fromUserDeleted, 
   f.toUserId, 
   f.toUserDeleted, 
   (SELECT count(*) FROM mail m1 WHERE m1.fromUserId=f.fromUserId AND m1.toUserId=f.toUserId) as messageCount 
FROM mail f 
WHERE 
   f.toUserId = 15 AND 
   f.toUserDeleted=0 
GROUP BY(f.fromUserId) 
ORDER BY 
   f.sentDate 
DESC 
   limit 0,100000

问题是这个命令会错过prev MySQL命令中显示的一些用户吗?

编辑1:

我试过这个:

SELECT m1.* 
FROM mail m1 
LEFT JOIN mail m2 ON(m1.fromUserId = m2.fromUserId AND m1.sentDate < m1.sentDate) 
WHERE m2.id IS NULL 
ORDER BY m1.sentDate;

它需要永远,不知道它是否真的会返回任何东西。

编辑2:

第二次尝试:

SELECT p1.id, p1.fromUserId, p1.fromUserNickName, p1.sentDate
FROM 
    mail p1 
INNER JOIN 
    (SELECT pi.id, MAX(pi.sentDate) as latestDate FROM mail pi GROUP BY pi.fromUserId) p2
    ON(p1.id = p2.id) 
WHERE 
    p1.toUserId = 15 
ORDER BY 
    p1.sentDate desc;

这不会返回已向用户发送邮件的所有用户15。

编辑3:

Barmar的第二个建议似乎有效:

SELECT m1.*, (SELECT count(*) FROM mail m3 WHERE m3.fromUserId=m1.fromUserId AND m3.toUserId=m1.toUserId) as messageCount 
FROM mail m1 
LEFT JOIN mail m2 ON (m1.fromUserId = m2.fromUserId 
                      AND m1.sentDate < m2.sentDate 
                      AND m2.toUserId = 15) 
WHERE m2.id IS NULL 
AND m1.toUserId = 15
ORDER BY m1.sentDate DESC;

1 个答案:

答案 0 :(得分:0)

在这两种情况下,您都不会将您加入的表格过滤到发送到您的ID的邮件。

第一种方法:

SELECT m1.* 
FROM mail m1 
LEFT JOIN mail m2 ON (m1.fromUserId = m2.fromUserId 
                      AND m1.sentDate < m2.sentDate 
                      AND m2.toUserId = 15) 
WHERE m2.id IS NULL 
AND m1.toUserId = 15
ORDER BY m1.sentDate DESC;

第二种方法:

SELECT p1.id, p1.fromUserId, p1.fromUserNickName, p1.sentDate
FROM 
    mail p1 
INNER JOIN 
    (SELECT pi.id, MAX(pi.sentDate) as latestDate 
     FROM mail pi 
     WHERE pi.toUserId = 15
     GROUP BY pi.fromUserId) p2
    ON (p1.id = p2.id) 
WHERE 
    p1.toUserId = 15 
ORDER BY 
    p1.sentDate desc;