如何使用 3 个表在 SQL 查询中获得完整结果,其中 1 个表保持 2 个表的关系?

Posted

技术标签:

【中文标题】如何使用 3 个表在 SQL 查询中获得完整结果,其中 1 个表保持 2 个表的关系?【英文标题】:How can I get full results in SQL query using 3 tables, where 1 of them keeps relation of 2 another? 【发布时间】:2020-09-30 14:12:57 【问题描述】:

我需要帮助编写查询以显示我想要的结果。

“表 3 - 关系”保留表 1 和表 2 之间的所有关系。通常,表 3 中不存在表 1 和 2 之间的关系,所以我想在结果中看到缺失的关系所有表 1 行 - 请参阅下面的预期结果。 我无法修改这些表 - 我只有 SELECT 权限。

数据和预期结果如下:

Table 1 - a:
a_id, a_name
e.g.: 
1 A
2 B

Table 2 - b:
b_id, b_name
e.g.: 
1 X
2 Y

Table 3 - relation:
asset1_id (it's always id from Table 1), asset2_id (it's always id from Table 2), relation_type
e.g.: 
1 1 covers
1 2 covers

预期结果:

Table1_name, Table2_name, Table3_relation_type  (including NULL for b_name and relation_type when such relation does not exist in Table 3 - relation)
e.g.
A X covers
A Y covers
B NULL NULL

我无法获得带有 NULL 的第三个预期行。

【问题讨论】:

表之间大概有关系吧。你应该解释它们是什么。 您必须在所有表中创建唯一的 Id,然后使用唯一的 Id 合并表。通过在表中创建主键和外键来使用SQL连接,并在连接这些表后获取数据。 我澄清了表之间的关系。我不能修改表,我只有 SELECT 权限。 检查这个,它可能对你有帮助。 ***.com/questions/2008853/… 上面的文章给了我没有我期望得到的第 3 行的结果 - 所以当表 1 的某些行在 Tbale 3 中没有关系时,我仍然看不到结果中的 NULL。 【参考方案1】:

我认为这个查询会产生这些结果。

select a.name as a_name,b.name as b_name, r.relation_type from relation r
join a on a.id=r.asset1_id
join b on b.id=r.asset2_id
union 
select a.name as a_name,b.name as b_name,r.relation_type from relation r
full outer join a on a.id=r.asset1_id
full outer join b on b.id=r.asset2_id
where a.id is null or b.id is null

【讨论】:

当表 1 中的项目与表 2 中的任何表 3 行都不匹配时,这种方式没有预期的 NULL。【参考方案2】:

有了你的数据样本,你可以试试这个。

它应该适用于 hive 或 impala。

SELECT t1.name ,t2.name ,r.relation_type 
FROM relation r
FULL OUTER JOIN table1 t1 ON(t1.id = r.id1)
FULL OUTER JOIN table2 t2 ON(t2.id = r.id2);

+------+------+---------------+
| name | name | relation_type |
+------+------+---------------+
| A    | X    | covers        |
| A    | Y    | covers        |
| B    | NULL | NULL          |
+------+------+---------------+

【讨论】:

这也没有让我得到预期的 NULL。我认为这是因为有很多关系类型,而我只对 r.type='Control' 感兴趣,并且在应用此过滤器时,我丢失了所有没有关系的表 1 行。【参考方案3】:
WITH 
    cte_A AS (
        SELECT id as a_id, name as a_name
        FROM a
        ),
    cte_C AS (
        SELECT c.asset_id1 as a_id, b.name, c.relation
        FROM c
            LEFT JOIN b ON c.id=b.asset_id2
        )

SELECT cte_A.a_name, cte_C.name as c_name, cte_C.relation
FROM cte_A
    LEFT JOIN cte_C ON cte_A.a_id=cte_C.a_id

【讨论】:

这完全符合预期,可能可以简化以避免第一次 cte。

以上是关于如何使用 3 个表在 SQL 查询中获得完整结果,其中 1 个表保持 2 个表的关系?的主要内容,如果未能解决你的问题,请参考以下文章

如何加入/子查询第二个表

在 SQL Server 上使用 3 个表连接时性能非常差

如何在T-SQL中使用递归CTE获得完整的层次结构?

T-SQL 选择连接 3 个表

sql server 中union的用法

如何在纯 SQL 中转换查询结果以获得更好的可读性