我有一个看起来像这样的消息表:
sender_id
我希望找到任意两个用户ID之间的第一条消息(recipient_id
和| id | sender_id | recipient_id |
|-------------------|---------------| ...
| 1 | 23 | 20 |
| 2 | 11 | 5 | ...
| 5 | 7 | 11 |
列中的ID)。因此上述样本的结果将是:
sender_id
起初我以为我可以通过recipient_id
和id
的校验和进行分组,然后获取最小消息ID(1. cd /
2. sudo ls
3. cd Applications
4. sudo ls
5. cd Xcode.app
6. cd Contents/MacOS
7. ls
8. ./Xcode
9. sudo ./Xcode
),但因为校验和因顺序而异输入,返回第一个消息(简介)和第一个回复。是否存在校验和的替代方案,其中输入的顺序无关紧要?
或许有更好的方法来达成解决方案。
非常感谢任何帮助。
答案 0 :(得分:4)
您可以使用ROW_NUMBER
:
WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER(
PARTITION BY
CASE WHEN sender_id < recipient_id THEN sender_id ELSE recipient_id END,
CASE WHEN sender_id > recipient_id THEN sender_id ELSE recipient_id END
ORDER BY id
) AS rn
FROM messages
)
SELECT
id, sender_id, recipient_id
FROM CTE
WHERE rn = 1
ORDER BY id
您需要使用较小的ID进行分区,然后使用CASE
表达式进行更大的分区。
答案 1 :(得分:1)
; WITH CTE(ID,SENDER_ID, RECIEPENT_ID) AS
(
SELECT 1,23,20 UNION
SELECT 2,11,5 UNION
SELECT 3,20,23 UNION
SELECT 4,23,20 UNION
SELECT 5,7 ,11
)
SELECT *, ROW_NUMBER() OVER (PARTITION BY ABS(SENDER_ID - RECIEPENT_ID) ORDER BY ID) RN FROM CTE
从此使用RN = 1
答案 2 :(得分:1)
CREATE TABLE messages
(
id int,
sender_id int,
recipient_id int
)
INSERT INTO messages
VALUES
(1,23,20),
(2,11,5),
(3,20,23),
(4,23,20),
(5,7,11)
SELECT
p.participant_1,
p.participant_2,
MIN(p.id)
FROM
(
SELECT
id,
participant_1 = sender_id,
participant_2 = recipient_id
FROM messages a
WHERE sender_id <= recipient_id
UNION ALL
SELECT
id,
participant_1 = recipient_id,
participant_2 = sender_id
FROM messages a
WHERE sender_id > recipient_id
) p
GROUP BY p.participant_1,
p.participant_2
答案 3 :(得分:0)
由于发件人和收件人都是整数标识符,如何以特定(例如升序)顺序连接它们?例如:
SELECT
CONCAT(CAST(MIN(sender_id, recipient_id) AS CHAR),
'-',
CAST(MAX(sender_id, recipient_id) AS CHAR)) AS pair,
MIN(id) AS id
FROM messages
GROUP BY pair
通过这种方式,无论哪个是发件人/收件人,我们都可以保证首先获得较低的数字,然后获得较高的数字。
请注意,如果您需要所请求的输出,则只需将messages
表加入id
上面的seqstring.raw
表即可获得确切的行。