Sql 选择与列表中所有项目匹配的行组
假设我有两个表:Sql 选择与列表中所有项目匹配的行组,sql,sql-server,tsql,relational-division,Sql,Sql Server,Tsql,Relational Division,假设我有两个表: 车辆–车辆列表 carname | modelnumber | ... passedtest–包含汽车通过的所有测试: id | carname | testtype | date | ... 1 | carA | A | 2000 | 2 | carB | C | 2000 | 3 | carC | D | 2001 | 4 | carA | C | 2002 | 现在,如何从pass
车辆
–车辆列表
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)的汽车
我在语句中尝试了,但它也匹配通过一次测试的汽车。我正在寻找一个语句来匹配所有行中列表中的所有值。这个怎么样
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
)
这种类型的问题称为关系划分
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
如果对表PassedTest
上的每个CarName
未对TestType
强制执行UNIQUE
约束,则COUNT()
上需要一个DISTINCT
关键字,因此它将只对唯一值进行计数
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
您希望执行关系除法,这是一种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);
+-------------+
|供应商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);
+-------------+
|供应商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
)
);
+-------------+
|供应商id|
+-------------+
| 1 |
| 2 |
+-------------+
谢谢,但我重复了我的输出,我想这是因为我使用了internal join来创建cars表。但是,这不适用于通配符,因为在这种情况下无法建立显式计数。但是我们正在硬编码4的值。。。如果我们添加一个测试呢?这应该是可以接受的答案,因为它不需要硬编码值