sql多次选择和连接行

时间:2015-04-20 04:01:05

标签: sql postgresql

我的查询多次选择行时遇到问题,而我的左连接多次加入行。

我查询的表看起来像这样。该表由wins分区。(这是示例数据)

+-----------+------------+------+---------+------+--+
| Player_ID |    name    | wins | matches | nrow |  |
+-----------+------------+------+---------+------+--+
|      4070 | Twilight   | 1L   | 1L      | 5L   |  |
|      4073 | Pinkie Pie | 1L   | 1L      | 3L   |  |
|      4071 | Fluttershy | 1L   | 1L      | 4L   |  |
|      4077 | jim        | 1L   | 1L      | 2L   |  |
|      4075 | mike       | 1L   | 1L      | 1L   |  |
|      4076 | sam        | 0L   | 1L      | 2L   |  |
|      4072 | Applejack  | 0L   | 1L      | 1L   |  |
|      4074 | gav        | 0L   | 1L      | 3L   |  |
+-----------+------------+------+---------+------+--+

,查询看起来像这样

SELECT player_standings.player_ID, matched_player.player_ID, player_standings.wins, player_standings.nrow, matched_player.nrow
FROM player_standings LEFT JOIN (
    SELECT player_ID, wins, nrow FROM player_standings
) AS matched_player ON
(matched_player.wins = player_standings.wins and matched_player.nrow % 2 = 0)
WHERE player_standings.nrow % 2 = 1;
在每隔一行选择

匹配的玩家,以避免在所有行上获得player1和player2列之间的重复值。我不能通过使用不等式运算符来实现同样的目的。

结果我看起来像这样

+---------+---------+------+--------------+--------------+
| player1 | player2 | wins | player1 nrow | player2 nrow |
+---------+---------+------+--------------+--------------+
|    4070 |    4071 | 1L   | 5L           | 4L           |
|    4075 |    4071 | 1L   | 1L           | 4L           |
|    4073 |    4077 | 1L   | 3L           | 2L           |
|    4074 |    4076 | 0L   | 3L           | 2L           |
|    4075 |    4077 | 1L   | 1L           | 2L           |
|    4073 |    4071 | 1L   | 3L           | 4L           |
|    4072 |    4076 | 0L   | 1L           | 2L           |
|    4070 |    4077 | 1L   | 5L           | 2L           |
+---------+---------+------+--------------+--------------+

注意玩家1和玩家2的重复值是多少。

总之,我想要的是,player1每行都有一个唯一的值。对于player2,我希望每行都有一个唯一值,或者如果查询中没有匹配的行,则值为'null'。

我想要的结果应该是这样的

+---------+---------+------+--------------+--------------+
| player1 | player2 | wins | player1 nrow | player2 nrow |
+---------+---------+------+--------------+--------------+
|    4070 |    4071 | 1L   | 5L           | 4L           |
|    4073 |    4077 | 1L   | 3L           | 2L           |
|    4074 |    4076 | 0L   | 3L           | 2L           |
|    4075 |    null | 1L   | 1L           | null         |
|    4072 |    null | 0L   | 1L           | null         |
+---------+---------+------+--------------+--------------+

1 个答案:

答案 0 :(得分:2)

我认为你所追求的是这个。基本上,正如我所理解的,你想要一个报告,其中信息以两列模式显示。通常这种类型的查询在窗口函数的帮助下解决。我用了ROW_NUMBER()

SQL Fiddle

PostgreSQL 9.3架构设置

CREATE TABLE player_standings
    (player_ID int, name varchar(10), wins varchar(2), matches varchar(2), nrow varchar(2))
;

INSERT INTO player_standings
    (player_ID, name, wins, matches, nrow)
VALUES
    (4070, 'Twilight', '1L', '1L', '5L'),
    (4073, 'Pinkie Pie', '1L', '1L', '3L'),
    (4071, 'Fluttershy', '1L', '1L', '4L'),
    (4077, 'jim', '1L', '1L', '2L'),
    (4075, 'mike', '1L', '1L', '1L'),
    (4076, 'sam', '0L', '1L', '2L'),
    (4072, 'Applejack', '0L', '1L', '1L'),
    (4074, 'gav', '0L', '1L', '3L')
;

查询1

SELECT player_standings1.player_ID, matched_player.player_ID, 
player_standings1.wins, player_standings1.nrow, matched_player.nrow
FROM (select *, ROW_NUMBER() OVER(PARTITION BY wins ORDER BY player_ID) rn from player_standings ) player_standings1 LEFT JOIN 
(select *, ROW_NUMBER() OVER(PARTITION BY wins ORDER BY player_ID) rn from player_standings ) matched_player 
ON player_standings1.wins = matched_player.wins AND player_standings1.rn = matched_player.rn+1
where player_standings1.rn%2=1
ORDER BY 3,1,2

<强> Results

| player_id | player_id | wins | nrow |   nrow |
|-----------|-----------|------|------|--------|
|      4072 |    (null) |   0L |   1L | (null) |
|      4076 |      4074 |   0L |   2L |     3L |
|      4070 |    (null) |   1L |   5L | (null) |
|      4073 |      4071 |   1L |   3L |     4L |
|      4077 |      4075 |   1L |   2L |     1L |

可以使用CTE编写相同的查询:

with withrn as (
select *, ROW_NUMBER() OVER(PARTITION BY wins ORDER BY player_ID) rn from player_standings)
SELECT player_standings1.player_ID, matched_player.player_ID, player_standings1.wins, player_standings1.nrow, matched_player.nrow
FROM withrn player_standings1 LEFT JOIN withrn matched_player 
ON player_standings1.wins = matched_player.wins AND player_standings1.rn = matched_player.rn+1
where player_standings1.rn%2=1
ORDER BY 3,1,2