Выбрать группу строк, которые соответствуют всем элементам списка
У меня есть две таблицы:
cars
– список автомобилей:
carname | modelnumber | ...
passedtest
– содержит информацию о каждом тесте, который прошел автомобиль:
id | carname | testtype | date | ...
1 | carA | A | 2000 |
2 | carB | C | 2000 |
3 | carC | D | 2001 |
4 | carA | C | 2002 |
Мне нужно выбрать автомобиль из таблицы passedtest
, который прошел все тесты (A, B, C, D).
Я пробовал использовать оператор IN
, но он также находит автомобили, которые проходят хотя бы один тест. Мне нужно составить запрос, который будет соответствовать всем значениям в списке по всем строкам.
Как правильно сформулировать такой запрос?
2 ответ(ов)
Ваш запрос выглядит вполне корректно. Вы используете подзапрос для выборки автомобилей, которые прошли 4 различных типа тестов.
Вот как он работает:
Во вложенном запросе (
SELECT carname FROM PassedTest GROUP BY carname HAVING COUNT(DISTINCT testtype) = 4
) вы выбираете только те автомобили (carname
), которые соответствуют условию, что количество уникальных типов тестов (testtype
) равно 4.Затем во внешнем запросе (
SELECT * FROM cars WHERE carname IN (...)
) вы выбираете все записи из таблицыcars
, где название автомобиля присутствует в списке автомобилей из подзапроса.
Это хороший подход, если вы хотите получить все детали о автомобилях, которые прошли определённые тесты. Убедитесь, что ваше условие HAVING подходит именно для вашей задачи – т.е. вам действительно нужно учитывать только автомобили, прошедшие 4 разных теста.
Если же вас интересует, например, только большее количество показателей или их отсутствие, возможно, вам стоит рассмотреть другие варианты фильтрации.
Если у вас есть дополнительные вопросы или уточнения по поводу структуры таблиц или данных, не стесняйтесь уточнять!
Вы хотите выполнить операцию деления в реляционных базах данных, которая не реализована в SQL. Рассмотрим пример с таблицами product-supplier и required-products:
CREATE TABLE product_supplier (
product_id int NOT NULL,
supplier_id int NOT NULL,
UNIQUE (product_id, supplier_id)
);
INSERT INTO product_supplier (product_id, supplier_id) VALUES
(1, 1),
(2, 1),
(3, 1),
(1, 2),
(2, 2),
(3, 2),
(4, 2),
(2, 3),
(3, 3),
(4, 3);
CREATE TABLE reqd (
product_id int NOT NULL,
UNIQUE (product_id)
);
INSERT INTO reqd (product_id) VALUES
(1),
(2),
(3);
Мы хотим найти всех поставщиков, которые снабжают ВСЕ необходимые продукты, а, возможно, и другие. Результат в этом примере будет поставщики 1 и 2.
Самый простой способ решения — это следующий запрос:
SELECT product_supplier.supplier_id
FROM product_supplier
LEFT JOIN reqd ON product_supplier.product_id = reqd.product_id
GROUP BY product_supplier.supplier_id
HAVING COUNT(reqd.product_id) = (SELECT COUNT(*) FROM reqd);
Этот запрос вернет:
+-------------+
| supplier_id |
+-------------+
| 1 |
| 2 |
+-------------+
Если мы хотим найти всех поставщиков, которые снабжают ВСЕ необходимые продукты и ничего лишнего (точное деление без остатка), то добавьте еще одно условие к вышеуказанному запросу:
SELECT product_supplier.supplier_id
FROM product_supplier
LEFT JOIN reqd ON product_supplier.product_id = reqd.product_id
GROUP BY product_supplier.supplier_id
HAVING COUNT(reqd.product_id) = (SELECT COUNT(*) FROM reqd)
AND COUNT(product_supplier.product_id) = (SELECT COUNT(*) FROM reqd);
Этот запрос вернет:
+-------------+
| supplier_id |
+-------------+
| 1 |
+-------------+
Альтернативное решение — переформулировать задачу: выбрать поставщиков, для которых не существует необходимого продукта, который не входит в перечень товаров, поставляемых этим поставщиком. Запрос будет выглядеть так:
SELECT DISTINCT supplier_id
FROM product_supplier AS ps1
WHERE NOT EXISTS (
SELECT *
FROM reqd
WHERE NOT EXISTS (
SELECT *
FROM product_supplier AS ps2
WHERE ps1.supplier_id = ps2.supplier_id AND ps2.product_id = reqd.product_id
)
);
Результатом этого запроса будет:
+-------------+
| supplier_id |
+-------------+
| 1 |
| 2 |
+-------------+
Таким образом, вы можете использовать оба подхода в зависимости от ваших целей и предпочтений.
"Вставка результатов хранимой процедуры в временную таблицу"
Как экранировать одинарную кавычку в SQL Server?
Как выполнить оператор UPDATE с JOIN в SQL Server?
Возможно ли задать условия в Count()?
Создание хранимой процедуры, если она еще не существует