在连接上生成连续数字

And*_*eKR 5 postgresql

对于 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专栏?

Vér*_*ace 6

您需要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 功能!