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 &lt; t2.id。另外,为什么left join?这没有任何意义。 @MikeOrganek 感谢您的意见。对 BigQuery 的工作方式有任何想法吗? @AbhayPai 。 . .如果您想要 BigQuery 的答案,请不要使用 Postgres 标签。 @GordonLinoff - 这个例子是 w.r.t. Postgres 因此是标签。我认为方言无关紧要,但是当我尝试运行查询时,我遇到了一些现在已经解决的问题。 【参考方案1】:

只需在连接条件中使用&lt;(或&gt;)而不是&lt;&gt;

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 表中记录的唯一组合(从节点表中获取边)的主要内容,如果未能解决你的问题,请参考以下文章

优化查询以从不同的表中获取唯一(用户)记录

从连接的两个表中获取前两个唯一记录 - Mysql

Sql 查询为表中的每个组合返回一条记录

如何使用sql从具有不同列的两个表中获取不同的记录

SQL - 如何从一个表中获取重复记录并连接到另一张表

获取两个表的差异以及重复记录并存储在 Azure SQL DB 的第三个表中