父/子联接查询,对子联接有无条件

问题描述 投票:-1回答:1

我有一个简单的一对多父/子关系,我基本上想执行左联接以在客户端的表中显示所有父数据:

SELECT p.*, c.* FROM parent p
LEFT JOIN child c ON c.parent_id = p.id

客户端可以为子级设置过滤条件,例如type = 42。在那种情况下,我仍然想在有任何子项匹配的情况下向有[[all个子项的父母显示。我使用以下查询执行此操作:

SELECT p.*, c.* FROM parent p [LEFF] JOIN child c ON c.parent_id = p.id WHERE EXISTS (SELECT 1 FROM child c2 WHERE c2.parent_id=p.id AND c2.type = 42) (1)
请注意,该连接实际上不再是左连接。

[当我在服务器上构建查询时,首先从基本查询开始,检查是否有子级的过滤条件,如果有,我将WHERE子句(1)添加到查询中。

[我想知道是否存在一个涵盖两种情况的查询(即,针对子项的过滤条件:是或否),在这里我可以简单地添加子项过滤条件(在没有过滤条件的情况下为1 = 1),而不必不必对是否存在过滤器标准进行初步区分。

谢谢。


编辑:

模式和示例数据

CREATE TABLE Parent ( id VARCHAR PRIMARY KEY ); CREATE TABLE Child ( id VARCHAR PRIMARY KEY, type INT, parent_id VARCHAR REFERENCES Parent(id) ); INSERT INTO Parent VALUES ('p1'), ('p2'), ('p3'), ('p4'); INSERT INTO Child VALUES ('c1', 0, 'p2'), ('c2', 42, 'p2'), ('c3', 0, 'p3'), ('c4', 42, 'p4');

SQL Fiddle

查询

我们总是与孩子一起询问父母。每当特定的父项成为结果的一部分时,在任何情况下都应检索

all

其子项。用例A)

对孩子没有限制-仅显示所有父母/孩子数据,包括没有孩子的父母(p1)。

上面的第一个LEFT JOIN查询产生所需的输出:

id|id|type| --|--|----| p1| | | p2|c1| 0| p2|c2| 42| p3|c3| 0| p4|c4| 42|

用例B)

对孩子有限制,例如type = 42。我们想检索有任何带有type = 42的孩子的父母(及其所有孩子),即所需的输出为:

id|id|type| --|--|----| p2|c1| 0| p2|c2| 42| p4|c4| 42|

请注意,即使c1的类型不匹配,也要检索其p2,因为其父c2具有匹配的子c1

具有相关子查询的第二个查询获得此结果。

问题

1)第二个查询是否是用例B)的标准方法?

2)由于在现实生活中存在多种关联和多种可能的过滤条件,是否有一种方法可以简化查询的整个结构,同时涵盖用例A)和B)?在某种意义上,可以通过各种子关联的条件来“丰富”“主查询”。如果是单个父表,则存在一个>>的“主查询”

SELEECT * from Parent p WHERE 1 = 1

可以将对父项的任何条件简单地AND设置为“主查询”的WHERE子句,从而使此查询构造非常容易。

在各种条件下对各种子项进行连接是否具有可比性,保留了“始终为每个返回的父项返回所有子项”的语义?

我有一个简单的一对多父/子关系,我基本上想执行左联接以在客户端的表中显示所有父数据:SELECT p。*,c。* FROM parent p LEFT JOIN child ...

sql join left-join parent-child correlated-subquery
1个回答
0
投票
话虽如此,使用窗口函数更简单:

SELECT p.*, c.* FROM parent p LEFT JOIN (SELECT c.*, SUM(CASE WHEN c.type = 42 THEN 1 ELSE 0 END) OVER (PARTITION BY c.parent_id) as num_42 FROM child c ) c ON c.parent_id = p.id AND num_42 > 0;

© www.soinside.com 2019 - 2024. All rights reserved.