对于 JOIN 中的每个右侧行,我想创建一个序列号,每个左侧行从 1(或 0)开始。
例子:
create table persons (person_id int, person_name text);
create table places (place_id int, person_id int, place_name text);
insert into persons values (10, 'Aulus Agerius'), (20, 'Numerius Negidius');
insert into places values (10, 10, 'Anytown'), (20, 10, 'Timbuktu'), (30, 20, 'Podunk');
Run Code Online (Sandbox Code Playgroud)
select person_name, place_name
from persons join places using (person_id)
order by person_id, place_id;
Run Code Online (Sandbox Code Playgroud)
期望的结果:
| 人名 | 地名 | 地点顺序 |
|---|---|---|
| 奥鲁斯·阿杰里乌斯 | 任意镇 | 1 |
| 奥鲁斯·阿杰里乌斯 | 廷巴克图 | 2 |
| 内吉迪乌斯 | 波敦克 | 1 |
例如,2 inplace_seq表示“这是为该人找到的第二个地方”。
如何创建place_seq专栏?
您需要ROW_NUMBER()(手动)窗口函数,如下所示(下面的代码显示在此处的小提琴上- 基于您自己的小提琴+1!):
SELECT
person_id,
place_id,
person_name,
place_name,
ROW_NUMBER()
OVER (PARTITION BY person_id ORDER BY place_id) AS rn
FROM persons
JOIN places using (person_id)
ORDER BY person_id, place_id;
Run Code Online (Sandbox Code Playgroud)
这是基于这样的假设:person_id&place_id至少UNIQUE或(更好)PRIMARY KEY其各自表的 s。可以想象,两个人可能有相同的名字 - 我认识两组三个人(独立 - 不是同一个家庭)具有相同的名字。至于地点,重复的情况更为常见。
结果:
person_name place_name rn
Aulus Agerius Anytown 1
Aulus Agerius Timbuktu 2
Numerius Negidius Podunk 1
Run Code Online (Sandbox Code Playgroud)
为了保证在不同的运行中获得一致的结果,ORDER BY窗口函数中的确定性子句是必要的。一般来说,ORDER BY如果我们希望结果具有确定性顺序,则 SQL 语句应该包含 ,窗口函数也应该包含 。
有关窗口函数,另请参阅此处和此处。这些功能非常强大,多次学习它们所付出的努力将会得到回报。网络上有很多关于它们的文章 - 我强烈建议您四处看看并练习,直到您(在某种程度上)掌握了它们。
首先,我强烈推荐 Bruce Momjian 的 YouTube 演示(此处的幻灯片)。Bruce Momjian 是全球首屈一指的 PostgreSQL 公司EnterpriseDB的副总裁兼“Postgres 布道者”。他也是一位出色的演讲者,很好地解释了 PostgreSQL 功能!
| 归档时间: |
|
| 查看次数: |
1147 次 |
| 最近记录: |