psql从单个表中获取一对

时间:2015-05-30 12:15:36

标签: sql postgresql

获得了一个包含列ID和NAME的User的简单表。

假设有一个偶数用户,我需要一个查询来配对它们,每个用户在一对或另一侧出现一个,而不再出现。

实施例

1 bob
2 joe
3 phil
4 ted
5 larry
6 jeremiah

成为:

bob joe
phil ted
larry jeremiah

到目前为止我已尝试过:

SELECT MIN(a.id) a, b.id b 
FROM users a 
JOIN users b 
on a.id < b.id 
GROUP by b.id;

但我只得到:

1 2
1 3
1 4
1 5
1 6

2 个答案:

答案 0 :(得分:4)

SELECT a.name
      , b.name
FROM users a
JOIN users b ON a.id % 2 = 1  -- a.id is odd
            AND b.id = a.id+1 -- b.id is odd+one (:=even)
  ;

添加row_number() - 技巧,如果你想在id中填补空白:

WITH seq AS (
        SELECT u.name , row_number() OVER (ORDER BY u.id) AS seq
        FROM users u
        )
SELECT a.name
      , b.name
FROM seq a
JOIN seq b ON a.seq % 2 = 1     -- a.seq is odd
            AND b.seq = a.seq+1 -- b.seq is odd+one (:=even)
  ;

要同时选择最后一个未配对的人,您可以使用左连接(并将奇数条件移动到where子句)

-- DELETE FROM users where id = 1;

WITH seq AS (
        SELECT u.name , row_number() OVER (ORDER BY u.id) AS seq
        FROM users u
        )
SELECT a.name
      , b.name
FROM seq a
LEFT JOIN seq b ON b.seq = a.seq+1 -- b.seq is odd+one (:=even)
WHERE a.seq % 2 = 1                -- a.seq is odd
  ;

答案 1 :(得分:2)

您可以使用条件聚合来处理此问题:

select max(case when id % 2 = 1 then name end),
       max(case when id % 2 = 0 then name end)     
from users u
group by (id - 1) / 2;

如果您没有顺序ID,则可以使用row_number()添加它们:

select max(case when seqnum % 2 = 1 then name end),
       max(case when seqnum % 2 = 0 then name end)     
from (select u.*, row_number() over (order by id) as seqnum from users u) u
group by (seqnum - 1) / 2;