如何在自联接中获取唯一值以及如何在 psql 中动态获取 LIMIT 数

Posted

技术标签:

【中文标题】如何在自联接中获取唯一值以及如何在 psql 中动态获取 LIMIT 数【英文标题】:How to get unique values in the self join and how to get LIMIT number dynamically in psql 【发布时间】:2016-02-13 20:23:05 【问题描述】:

您好,我只是在学习数据库并在下表中练习我的技能

id  |       name        | wins | matches 
-----+-------------------+------+---------
 205 | Twilight Sparkle  |    0 |       0
 206 | Fluttershy        |    0 |       0
 207 | Applejack         |    0 |       0
 208 | Pinkie Pie        |    0 |       0
 209 | Rarity            |    0 |       0
 210 | Rainbow Dash      |    0 |       0
 211 | Princess Celestia |    0 |       0
 212 | Princess Luna     |    0 |       0

我的工作在这里 返回下一轮比赛的球员对列表。 假设注册的玩家数量为偶数,每个玩家 在配对中只出现一次。每个玩家都与另一个配对 获胜记录相等或几乎相等的玩家,即在积分榜上与他或她相邻的玩家。

返回: 元组列表,每个元组包含 (id1, name1, id2, name2) id1:第一个玩家的唯一id name1:第一个玩家的名字 id2:第二个玩家的唯一id name2:第二个玩家的名字

为了实现这些目标,我已经完成了自我加入该表并编写了类似这样的代码

SELECT a.id, a.name, b.id, b.name 
FROM results AS a, results AS b 
WHERE a.id > b.id and a.wins = b.wins 
LIMIT COUNT(a.id)/2;  

好像不行。请帮我解决这个问题。

谢谢。

【问题讨论】:

您使用的是 mysql 还是 PostgreSQL? - 它们是两个不同的关系型数据库 我正在使用 PostgreSQL。 【参考方案1】:

您可以根据他们的胜利对他们进行排序,然后加入该序列,因此他们可能获得相同的胜利或下一个最接近的胜利:

WITH seq_results AS
(
SELECT
    id,
    name,
    ROW_NUMBER() OVER(ORDER BY wins DESC) AS seq
FROM
    results
)

SELECT
    r1.id,
    r1.name,
    r2.id,
    r2.name
FROM
    seq_results r1
JOIN
    seq_results r2
    ON  (r1.seq = (r2.seq - 1))
    AND (r2.seq % 2 = 0);

根据您的要求,以下是有关其工作原理的一些信息。我强烈建议您访问 PostgreSQL 的文档 - 它确实是一些最好的文档:http://www.postgresql.org/docs/current/static/

第一部分是公用表表达式 (CTE)。它允许我在内存中创建一个表以供后续查询使用。您可以轻松地创建一个临时表,但不必删除这些等。 见:http://www.postgresql.org/docs/current/static/queries-with.html

WITH seq_results AS
(
SELECT
    id,
    name,
    ROW_NUMBER() OVER(ORDER BY wins DESC) AS seq
FROM
    results
)

在这个 CTE 中,我使用窗口函数对每条记录进行排序/顺序编号。稍后我将在加入时使用这些数字。见:http://www.postgresql.org/docs/current/static/functions-window.html

SELECT
    r1.id,
    r1.name,
    r2.id,
    r2.name
FROM
    seq_results r1
JOIN
    seq_results r2
    ON  (r1.seq = (r2.seq - 1))
    AND (r2.seq % 2 = 0);

在上面,我使用序列将 CTE 加入到自身中。我将 CTE r2 的第二个实例的序列“偏移”了 -1,本质上是将两个连续记录连接在一起。

如果我只在连接中指定该条件,我会返回超过预期的 4 条记录。我需要确保“左侧”上的 id 和名称不在“右侧”上,因此我决定仅包括左侧的奇数序列记录和右侧的偶数记录。为此,我使用了模运算符% 来确保r2 只返回序列为偶数的记录。

最后,因为连接是内连接(JOININNER JOIN 相同),所以不会返回 r1 中的任何偶数序列。

【讨论】:

我不知道你为什么要在查询前加上create table,但逻辑是正确的。 这有什么不明白的?表seq_results在最终查询中被使用了两次,所以它不能是CTE。 嗨,我收到此错误ValueError: For eight players, swissPairings should return 4 pairs. Got 3 我认为列表中缺少一些我尝试左连接但我得到 8 对。我认为超过 2 人的分数相同。 嗨,我收到此错误ValueError: For eight players, swissPairings should return 4 pairs. Got 3 我认为列表中缺少一些我尝试过左连接但我得到 8 对。我认为超过 2 人的分数相同。 这个错误来自哪里? ValueError: For eight players, swissPairings should return 4 pairs. Got 3

以上是关于如何在自联接中获取唯一值以及如何在 psql 中动态获取 LIMIT 数的主要内容,如果未能解决你的问题,请参考以下文章

了解在 SQL 查询的自联接中使用“Between”条件时的逻辑查询处理

如何在单个查询 (PSQL) 中更新一列中的不同值?

如何在 psql 中获取当前月份星期日的计数?

PSQL - 查找所有值并根据另一列中的非唯一值使其唯一

执行 psql/mysql CLI 命令行后如何获取查询 ID?

如何获取数组中的唯一值[重复]