48

假设我有两张桌子:

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声明,但它也与通过一项测试的汽车相匹配。我正在寻找一个语句来匹配列表中所有行的所有值。

4

3 回答 3

44

这个怎么样?

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
)
于 2013-04-12T17:11:19.660 回答
43

这种类型的问题称为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强制执行约束,则需要关键字,因此它只会计算唯一值。TestTypeCarNamePassedTestDISTINCTCOUNT()

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
于 2013-04-12T17:11:28.407 回答
12

您想要执行关系除法,这是一种在 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 |
+-------------+
于 2018-02-10T11:49:59.713 回答