假设我有两个表:
cars
- 汽车列表
carname | modelnumber | ...
passedtest
- 包含汽车通过的每项测试:
id | carname | testtype | date | ...
1 | carA | A | 2000 |
2 | carB | C | 2000 |
3 | carC | D | 2001 |
4 | carA | C | 2002 |
现在,如何从通过所有测试(A,B,C,D)的passedtest
表中选择一辆汽车?
我尝试了IN
声明,但它也匹配通过一次测试的汽车。我正在寻找一个语句来匹配所有行中列表中的所有值。
答案 0 :(得分:39)
这个怎么样?
SELECT carname
FROM PassedTest
GROUP BY carname
HAVING COUNT(DISTINCT testtype) = 4
您还可以将其用作从cars
表中获取信息的内部声明:
SELECT *
FROM cars
WHERE carname IN (
SELECT carname
FROM PassedTest
GROUP BY carname
HAVING COUNT(DISTINCT testtype) = 4
)
答案 1 :(得分:31)
此类问题称为Relational Division
。
SELECT a.*
FROM Cars a
INNER JOIN
(
SELECT CarName
FROM PassedTest
WHERE testType IN ('A', 'B', 'C', 'D')
GROUP BY CarName
HAVING COUNT(*) = 4
) b ON a.CarName = b.CarName
如果UNIQUE
对表TestType
上的每个CarName
强制执行PassedTest
约束,则DISTINCT
需要COUNT()
个关键字,它只会计算唯一值。
SELECT a.*
FROM Cars a
INNER JOIN
(
SELECT CarName
FROM PassedTest
WHERE testType IN ('A', 'B', 'C', 'D')
GROUP BY CarName
HAVING COUNT(DISTINCT TestType) = 4
) b ON a.CarName = b.CarName
但如果您只对CARNAME
感兴趣,那么您不需要加入表格。查询表PassedTest
将符合您的需求。
SELECT CarName
FROM PassedTest
WHERE testType IN ('A', 'B', 'C', 'D')
GROUP BY CarName
HAVING COUNT(*) = 4
答案 2 :(得分:3)
您想要执行关系除法,这是一种未在SQL中实现的操作。以下是我们拥有产品供应商表和必需产品表的示例:
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 |
+-------------+