问题
I have some problem with my SQL query
I have table message
and table recipient
message
is
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
is
ID m_id recipient
--------------------
0 0 2
1 1 2
2 2 3
3 3 2
4 4 1
5 5 2
I need return rows from table message
with group by recipient column from table recipient
with last date in message
table
I'll try this
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
return is
ID author date
--------------------
2 1 2013-07-15 05:38:47
0 1 2013-07-08 05:38:47
but i need
ID author date
--------------------
5 1 2013-07-28 05:38:47
2 1 2013-07-15 05:38:47
please help
I USE MySQL Server 5.1
I found a solution to my problem
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
just reverse table recipient
回答1:
Very simple and fast in PostgreSQL with DISTINCT ON
- not standard SQL so not available in every RDBMS.
The question doesn't mention it, but deriving from the code examples it is actually looking for the row with the "last date" for each recipient for a given 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
Details as well as multiple SQL standard alternatives here:
Select first row in each GROUP BY group?
Another solution with basic, standard SQL. Works with every major RDBMS, including MySQL (since that tag has been added):
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
)
Only the row with the latest date passes the NOT EXISTS
anti-semi-join.
回答2:
Presuming you're using SQL-Server, you can use a ranking function like 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
Demo
来源:https://stackoverflow.com/questions/18164798/sql-group-by-from-other-table-and-invert-result