SQL Выберите все строки, где существует подмножество - PullRequest
4 голосов
/ 08 декабря 2011

Я уверен, что есть ответ на этот вопрос, но потерпите меня, поскольку я новичок в SQL и не знаю, как задать вопрос.

У меня есть такие данные (этостенография чисто например).Это в postgres db.

table1
id    value
1     111
1     112
1     113
2     111
2     112
2     116
3     111
3     122
3     123
4     126
5     123
5     125
6     111
6     112
6     116

table2
value
111
112
116

Мне нужно вернуть идентификатор table1, где все значения в table2 существуют в значениях table1.Таким образом, для этого примера мой запрос вернул бы 2 и 6.

Есть ли способ сделать это в SQL?Или вы могли бы привести меня к структуре данных, которая позволила бы мне получить этот результат?Я могу изменить структуру любой таблицы, чтобы удовлетворить конечную необходимость получения этого результата

Большое вам спасибо.Ответом на это станет спасение жизни.

Ответы [ 4 ]

6 голосов
/ 08 декабря 2011

Рассмотрим эту демонстрацию:

CREATE TEMP TABLE table1(id int, value int);
INSERT INTO table1 VALUES
 (1,111),(1,112),(1,113)
,(2,111),(2,112),(2,116)
,(3,111),(3,122),(3,123)
,(4,126)
,(5,123),(5,125)
,(6,111),(6,112),(6,116);

CREATE TEMP TABLE table2(value int);
INSERT INTO table2 VALUES
 (111)
,(112)
,(116);

SELECT t1.id
FROM   table1 t1
JOIN   table2 t2 USING (value)
GROUP  BY t1.id
HAVING count(*) = (SELECT count(*) FROM table2)
ORDER  BY t1.id;

Результат:

id
-----
2
6

Возвращает все идентификаторы table1, которые появляются со всеми значениями, предоставленными table2 один раз.
Работает для любого количества строк в обеих таблицах.

Если в table1 могут появиться повторяющиеся строки, сделайте это:

HAVING count(DISTINCT value) = (SELECT count(*) FROM table2) 
3 голосов
/ 08 декабря 2011

Мне кажется, что столько, сколько вы хотите знать, как задать правильный вопрос. Волшебные слова здесь - «реляционное разделение».

Это один из операторов в реляционной алгебре Кодда , и с тех пор было предложено несколько вариантов. Совсем недавно Крис Дата предложил заменить всю концепцию на отношения изображений .

В SQL нет явного оператора деления. Существует несколько обходных путей с использованием другого оператора, и наиболее подходящий будет зависеть от ваших требований, включая точное деление или деление с остатком и способ обработки пустого делителя. Тогда есть обычные соображения: продукт и версия SQL, производительность, личный стиль и вкус и т. Д.

Вот пара статей, которые должны помочь вам с этими вариантами:

О том, как сделать реляционное деление понятным

Разделенное Мы стоим: SQL реляционного разделения

1 голос
/ 08 декабря 2011

ОБНОВЛЕНИЕ Другая возможность:

SELECT t1.id
FROM (SELECT t1.id, t1.value
      FROM table1 t1
      JOIN  table2 t2 USING (value)
      GROUP BY t1.id, t1.value
      ORDER BY t1.id) t1
GROUP BY t1.id      
HAVING COUNT(*) = (SELECT COUNT(*) FROM table2)

Стоимость моего ответа, если вы используете EXPLAIN ANALYZE , всегда равна 893-900, даже с повторяющимися строками.

0 голосов
/ 31 августа 2016

NOT EXISTS (... NOT EXISTS) является стандартным решением для реляционного деления:

SELECT DISTINCT id
FROM table1 t1
WHERE NOT EXISTS (
        SELECT * FROM table2 t2
        WHERE NOT EXISTS (
                SELECT * FROM table1 t1x
                WHERE t1x.value = t2.value
                AND t1x.id = t1.id
                )
        )
        ;

В этом случае DISTINCT необходим, потому что мы неиметь доступ к таблице domain с id s, только к junction таблице t1, ссылающейся на нее.

...