SQL 表中记录的唯一组合(从节点表中获取边)
Posted
技术标签:
【中文标题】SQL 表中记录的唯一组合(从节点表中获取边)【英文标题】:Unique combination of records in a SQL table (Get edges from nodes table) 【发布时间】:2020-09-03 07:00:59 【问题描述】:我遇到了一个用例,我想生成一个组合表,其中记录的属性必须与表中的所有其他记录匹配。类似于使用节点表在完整图中创建边列表。
为了给你一个需求的例子,你可以考虑下表(Postgres)。
create table test_users
(
id uuid default uuid_generate_v4(),
first_name text,
last_name text
);
我使用以下插入查询向表中添加了一些记录
INSERT INTO public.test_users (id, first_name, last_name) VALUES ('3ef309db-07cd-4e3f-95db-406f8165e54d', 'john', 'doe');
INSERT INTO public.test_users (id, first_name, last_name) VALUES ('50f33b51-1d3a-463c-9d5a-6f0b2c15cba2', 'marry', 'poppins');
INSERT INTO public.test_users (id, first_name, last_name) VALUES ('9812fbcf-d269-47a4-801d-2a8916e114e1', 'tony', 'stark');
INSERT INTO public.test_users (id, first_name, last_name) VALUES ('8d7b8d00-9602-4a12-914d-3df6a40d2716', 'idris', 'alba');
INSERT INTO public.test_users (id, first_name, last_name) VALUES ('2dee874f-f41e-4d68-a341-45e0a18079df', 'john', 'frusciante');
你会得到下表
id | first_name | last_name
--------------------------------------+------------+------------
3ef309db-07cd-4e3f-95db-406f8165e54d | john | doe
50f33b51-1d3a-463c-9d5a-6f0b2c15cba2 | marry | poppins
9812fbcf-d269-47a4-801d-2a8916e114e1 | tony | stark
8d7b8d00-9602-4a12-914d-3df6a40d2716 | idris | alba
2dee874f-f41e-4d68-a341-45e0a18079df | john | frusciante
现在我想创建这些名称的组合,这样一行的first_name
应该具有所有可能的组合,例如(f1, f2) = (f2, f1)
。为您提供更多上下文,预期输出应如下所示。
first_name | first_name | last_name | last_name
------------+------------+------------+------------
john | marry | doe | poppins
john | tony | doe | stark
john | idris | doe | alba
john | john | doe | frusciante
marry | tony | poppins | stark
marry | idris | poppins | alba
marry | john | poppins | frusciante
tony | idris | stark | alba
tony | john | stark | frusciante
idris | john | alba | frusciante
您可以看到first_name
的第 1 列和第 2 列的组合在表格中是唯一的。
我能达到的最接近的是使用以下查询进行内部联接。
select t1.first_name,
t2.first_name,
t1.last_name,
t2.last_name
from test_users t1
left join test_users t2 on t1.id <> t2.id;
但这会产生(f1, f2) != (f2, f1)
的所有记录,因此会创建冗余记录。有没有办法使用 SQL 从完整图中的节点列表中获取唯一的边列表?
【问题讨论】:
在连接中使用t1.id < t2.id
。另外,为什么left join
?这没有任何意义。
@MikeOrganek 感谢您的意见。对 BigQuery 的工作方式有任何想法吗?
@AbhayPai 。 . .如果您想要 BigQuery 的答案,请不要使用 Postgres 标签。
@GordonLinoff - 这个例子是 w.r.t. Postgres 因此是标签。我认为方言无关紧要,但是当我尝试运行查询时,我遇到了一些现在已经解决的问题。
【参考方案1】:
只需在连接条件中使用<
(或>
)而不是<>
:
select
t1.first_name first_name1,
t2.first_name first_name2,
t1.last_name last_name1,
t2.last_name last_name2
from test_users t1
inner join test_users t2 on t1.id < t2.id
注意事项:
您可能希望为结果集中的列加上别名,以消除来自两个表的列的歧义
不需要left join
- inner join
可以满足您的需求
【讨论】:
以上是关于SQL 表中记录的唯一组合(从节点表中获取边)的主要内容,如果未能解决你的问题,请参考以下文章