- 订购了 ID 为 100 的商品的客户的姓名。
我们可以通过首先运行查询来查找包含给定商品 ID 的订单的客户 ID,然后查找客户姓名。这是通过IN 子句完成的。
SELECT c.cname
FROM Customer c
WHERE c.cid IN (
SELECT o.cid
FROM Order o
WHERE o.iid = 100
)
一个客户只会被返回一次,这是由 IN 子句的 Set 语义保证的,但如果数据库允许多个客户具有相同的名称,则可能会多次返回相同的客户名称。
要只返回一次客户名称,即使有多个同名客户,我们也可以使用DISTINCT 子句。如果这样做,我们可以将查询更改为使用普通的JOIN。
SELECT DISTINCT c.cname
FROM Order o
JOIN Customer c ON c.cid = o.cid
WHERE o.iid = 100
哪个更好取决于口味,我相信它们的表现大致相同。就个人而言,我更喜欢第一个。
- 订购了笔记本电脑(即“笔记本电脑”类型的商品)的客户的姓名。
与以前相同,但针对Item 表使用WHERE 条件。
SELECT c.cname
FROM Customer c
WHERE c.cid IN (
SELECT o.cid
FROM Item i
JOIN Order o ON o.iid = i.iid
WHERE i.type = 'laptop'
)
SELECT DISTINCT c.cname
FROM Item i
JOIN Order o ON o.iid = i.iid
JOIN Customer c ON c.cid = o.cid
WHERE i.type = 'laptop'
- 订购了笔记本电脑和台式电脑的客户。
已订购所有商品的客户姓名
当使用IN 子句时,我们只需要执行两次,即可找到同时订购的客户。
SELECT c.cname
FROM Customer c
WHERE c.cid IN (
SELECT o.cid
FROM Item i
JOIN Order o ON o.iid = i.iid
WHERE i.type = 'laptop'
)
AND c.cid IN (
SELECT o.cid
FROM Item i
JOIN Order o ON o.iid = i.iid
WHERE i.type = 'desktop'
)
对于另一种方式,我们需要使用GROUP BY 而不是DISTINCT,以便我们可以检查客户是否同时订购了两者。
SELECT DISTINCT c.cname
FROM Item i
JOIN Order o ON o.iid = i.iid
JOIN Customer c ON c.cid = o.cid
WHERE i.type IN ('laptop', 'desktop')
GROUP BY c.cid, c.cname
HAVING COUNT(DISTINCT i.type) = 2
或者我们可以混合两种风格。
SELECT c.cname
FROM Customer c
WHERE c.cid IN (
SELECT o.cid
FROM Item i
JOIN Order o ON o.iid = i.iid
WHERE i.type IN ('laptop', 'desktop')
GROUP BY o.cid
HAVING COUNT(DISTINCT i.type) = 2
)
第三个可能是性能最好的。