Решить это для общего случая поиска всех подходящих родителей гораздо веселее :) См. Примечание внизу, как это можно использовать для более простого случая (один из родительских ключей фиксирован).
Я дам, как мне кажется, «правильное» решение, но у меня нет копии Access (или SQL Server), чтобы посмотреть, работает ли она там. (Да, я проверил это с БД здесь ...)
SELECT p1.column1, p2.column1
FROM parent p1 JOIN parent p2 ON p1.column1 < p2.column1
WHERE NOT EXISTS (SELECT 1
FROM (SELECT c1.column1, c1.column2 FROM child c1 WHERE c1.column1 = p1.column1) c1f
FULL OUTER JOIN
(SELECT c2.column1, c2.column2 FROM child c2 WHERE c2.column1 = p2.column1) c2f
ON c1f.column2 = c2f.column2
WHERE c1f.column1 IS NULL OR c2f.column1 IS NULL
);
Так что, надеюсь, вы можете увидеть, как то, что я сказал выше, связано в этом :) Я постараюсь объяснить ...
«Внешний» (первый) выбор генерирует комбинации значений column1 (p1.column1 и p2.column1). Для каждой из этих комбинаций мы перечисляем строки в «потомках» для этих значений (это c1f и c2f: c1f означает «фильтрованный потомок 1») и выполняем FULL OUTER JOIN. По моему опыту, это сравнительно редкая конструкция. Мы хотим сопоставить все записи в c1f и c2f (используя их значения для column1) и найти любое значение с каждой стороны , которое не имеет соответствующей записи на другой стороне. Если есть такие несоответствия, они будут отображаться в виде строк в соединении с нулем для их значения column1. Таким образом, родительский запрос выбирает только комбинации значений column1, если таких строк в подзапросе не существует, то есть каждая дочерняя строка для значения column1 p1 имеет соответствующую дочернюю строку для значения column1 p2 и наоборот.
Так, например, для итерации, где p1.column1 - это «S1», а p2.column2 - «S3», этот подзапрос (без агрегирования) будет производить:
c1f__column1 | c1f__column2 | c2f__column1 | c2f__column2
--------------+--------------+--------------+--------------
S1 | P1 | S3 | P1
S1 | P2 | |
и эти нули во втором ряду помечают эту комбинацию как несоответствующую. Вовлечены некоторые изворотливые мысли, заманчиво зацикливаться на поиске подходящих комбинаций, когда легче найти несоответствующие.
В качестве заключительного бонуса, когда я создал для этого несколько тестовых таблиц, я сделал (column1, column2) первичный ключ child, который оказался именно тем, что вам нужно для полного внешнего объединения отфильтрованных таблиц. эффективно. Выиграть! (Так что учтите, что я не пытался справиться с дублирующимися комбинациями в child ... но вы могли бы просто указать "отличные" в деривациях c1f и c2f)
Примечание: на основании комментария Мэтта, если одно из ваших родительских значений было известно (т.е. вы просто хотели перечислить все родительские значения с теми же дочерними элементами, что и S1), тогда вы можете просто дать пощечину "и p1.column1 = 'S1'" в конце этого. Но в этом случае замените «parent p1 JOIN parent p2 ON p1.column1