我必须获得两列的独特组合。
例如,如果值是:
sender_id recipient_id created_at
1 2 10/11/2014
2 1 10/12/2014
1 2 10/13/2014
1 3 10/14/2014
我希望输出为:
sender_id recipient_id created_at
1 3 10/14/2014
1 2 10/13/2014
我写了这个查询:
SELECT DISTINCT ON (sender_id, recipient_id) *
FROM "messages"
WHERE ((recipient_id = 1 and recipient_delete = false)
or (sender_id = 1 and sender_delete = false))
ORDER BY sender_id, recipient_id, created_at DESC
但它输出了这个:
sender_id recipient_id created_at
1 3 10/14/2014
2 1 10/12/2014
1 2 10/13/2014
答案 0 :(得分:3)
DISTINCT ON
的初步想法很好,但是:
DISTINCT ON()
是PostgreSQL的非标准扩展。因此,对postgres应该有效并且有效的密切查询是:
SELECT DISTINCT ON (pair) *,
CASE WHEN sender_id<recipient_id
THEN (sender_id,recipient_id)
ELSE (recipient_id,sender_id)
END AS pair
FROM messages
ORDER BY pair, created_at DESC ;
答案 1 :(得分:2)
获取所有对的一个选项,无论它们是向前还是向后(例如(1,2)==(2,1)),都要从中选择LEAST()
和GREATEST()
每行,然后选择不同的值。使用此查询:
SELECT DISTINCT LEAST(sender_id, recipient_id), GREATEST(sender_id, recipient_id)
FROM myTable;
您将获得以下输出:
| 1 | 2 |
| 1 | 3 |
一旦你有了这个,你可以通过这些来获得每对的最大日期:
SELECT LEAST(sender_id, recipient_id), GREATEST(sender_id, recipient_id), MAX(created_at)
FROM myTable
GROUP BY LEAST(sender_id, recipient_id), GREATEST(sender_id, recipient_id);
此查询将为您提供每对所需的数据,但不会返回原始表中的实际行。如果有一行格式为| 2 | 1 | 2014-10-15 |
,则此查询将返回| 1 | 2 | 2014-10-15
。
要获取表格中的原始行,您需要JOIN
,条件是所有必要的列都匹配:
SELECT m.*
FROM myTable m
JOIN(
SELECT LEAST(sender_id, recipient_id) AS least,
GREATEST(sender_id, recipient_id) AS greatest,
MAX(created_at) AS maxDate
FROM myTable
GROUP BY LEAST(sender_id, recipient_id), GREATEST(sender_id, recipient_id)) tmp
ON tmp.least = LEAST(m.sender_id, m.recipient_id) AND tmp.greatest = GREATEST(m.sender_id, m.recipient_id) AND tmp.maxDate = m.created_at;
以下是符合预期结果的SQL Fiddle示例。