-1

我的 SQL 查询有问题 我有表message和表recipient

message

ID    author    date
--------------------
0        1      2013-07-08 05:38:47
1        1      2013-07-13 05:38:47
2        1      2013-07-15 05:38:47
3        1      2013-07-15 05:38:47
4        2      2013-07-17 05:38:47
5        1      2013-07-28 05:38:47

recipient

ID    m_id    recipient
--------------------
0        0      2
1        1      2
2        2      3
3        3      2
4        4      1
5        5      2

我需要从表中返回行,从表中最后日期的表中message收件人列分组我会试试这个recipientmessage

SELECT m.* 
FROM message as m
INNER JOIN recipient as r ON (m.ID = r.m_id)
WHERE m.author = 1
GROUP BY r.recipient
ORDER BY m.ID DESC

回报是

ID    author    date
--------------------
2        1      2013-07-15 05:38:47
0        1      2013-07-08 05:38:47

但是我需要

ID    author    date
--------------------
5        1      2013-07-28 05:38:47
2        1      2013-07-15 05:38:47

请帮忙

我使用 MySQL 服务器 5.1


我找到了解决问题的方法

SELECT m.* 
FROM (
SELECT * FROM recipient 
    WHERE 1=1
    ORDER BY recipient.ID DESC
) AS r
INNER JOIN message AS m ON (r.m_id = m.ID)
WHERE m.author = 1
GROUP BY r.recipient

只是反转表recipient

4

2 回答 2

2

在PostgreSQL中非常简单和快速DISTINCT ON- 不是标准 SQL,因此并非在每个 RDBMS 中都可用。

问题没有提到它,但从代码示例中得出,它实际上是在为给定author的每个收件人寻找带有“最后日期”的行。

SELECT DISTINCT ON (r.recipient)  m.*
FROM   message   m
JOIN   recipient r ON r.m_id = m.id
WHERE  m.author = 1
ORDER  BY r.recipient, m.date DESC, r.m_id -- to break ties

此处提供详细信息以及多个 SQL 标准替代方案:
选择每个 GROUP BY 组中的第一行?

另一种具有基本标准 SQL 的解决方案。适用于所有主要的 RDBMS,包括MySQL(因为已添加该标签):

SELECT m.* 
FROM   message   m
JOIN   recipient r ON r.m_id = m.id
WHERE  m.author = 1
AND NOT EXISTS (
   SELECT 1
   FROM   message   m1
   JOIN   recipient r1 ON r1.m_id = m1.id
   WHERE  r1.recipient = r.recipient 
   AND    m1.author = 1
   AND    m1.date > m.date
   )

只有日期最近的行才能通过NOT EXISTS反半连接。

于 2013-08-10T18:24:24.030 回答
1

假设您使用的是 SQL-Server,您可以使用如下排名函数ROW_NUMBER

WITH CTE AS(
    SELECT m.*,
      RN=ROW_NUMBER()OVER(PARTITION BY r.recipient ORDER BY  m.date DESC)
    FROM message as m
    INNER JOIN recipient as r ON (m.ID = r.m_id)
    WHERE m.author = 1
)
SELECT * FROM CTE WHERE RN = 1

演示

于 2013-08-10T18:02:00.373 回答