我有一个简单的一对多父/子关系,我基本上想执行左联接以在客户端的表中显示所有父数据:
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其子项。用例A)查询
我们总是与孩子一起询问父母。每当特定的父项成为结果的一部分时,在任何情况下都应检索
all
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 ...
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;