Схема и примеры данных
Простые отношения один-ко-многим родитель / ребенок:
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 Скрипка
Запросы
Мы всегда запрашиваем родителей со своими детьми. Когда конкретный родитель является частью результата, все его дочерние элементы также должны быть извлечены, в любом случае.
Вариант использования A)
Нет ограничений для дочерних элементов - просто отобразите все данные родителей / детей, включая родителей без детей (p1
).
Запрос LEFT JOIN
SELECT p.*, c.* FROM parent p
LEFT JOIN child c ON c.parent_id = p.id
дает желаемый результат:
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
не соответствует.
Этот запрос с коррелированным подзапросом достигает этого результата:
SELECT p.*, c.* FROM parent p
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 EXISTS
стандартным способом go для варианта использования B)?
2) Поскольку в действительности жизнь, существует несколько ассоциаций и несколько возможных условий фильтрации, есть ли способ упростить всю конструкцию запроса, охватывающую оба варианта использования A) и B)? В смысле «основного запроса», который может быть «обогащен» условиями для различных дочерних ассоциаций. В случае с одной родительской таблицей существует «главный запрос»
SELEECT * from Parent p
WHERE 1 = 1
. Любые условия для родительского элемента можно просто AND
'отредактировать в предложении WHERE
«основного запроса». , что делает эту конструкцию запроса очень простой.
Есть ли что-нибудь сопоставимое для объединений с различными условиями для разных потомков, сохраняя семантику "всегда возвращать всех потомков для каждого возвращенного родителя"?