【问题标题】:SQL Server - Sakila DBSQL Server - Sakila DB
【发布时间】:2020-04-25 18:20:03
【问题描述】:

我目前正在使用 MS 的 Sakila DB,其中包含有关电影/演员/租赁/客户等的数据。

地图:

我被要求制定一个查询来查找没有租借特定电影的客户。

我已经能够计算出找到租用该影片的客户的代码,但我无法找到没有租用该影片的客户的名单。

我的代码如下:

SELECT DISTINCT C.customer_id, C.first_name, C.last_name
FROM customer AS C
JOIN RENTAL AS R ON C.customer_id = R.customer_id
JOIN inventory AS I ON R.inventory_id = I.inventory_id
JOIN film AS F ON I.film_id = F.film_id
WHERE F.title = 'ANGELS LIFE'

我可以使用!= 'ANGELS LIFE',但它会返回给我所有租借过任何其他电影的人的名单(包括那些从其他购买中租借过 ANGELS LIFE 的人)。

我无法完成下一步。我考虑过使用Union,然后删除重复项(其中 count(*) >1)也许?

感谢任何建议。

【问题讨论】:

    标签: sql sql-server tsql join


    【解决方案1】:

    你可以使用聚合:

    SELECT C.customer_id, C.first_name, C.last_name
    FROM customer AS C JOIN 
         RENTAL AS R 
         ON C.customer_id = R.customer_id JOIN 
         inventory AS I 
         ON R.inventory_id = I.inventory_id JOIN 
         film AS F 
         ON I.film_id = F.film_id
    GROUP BY C.customer_id, C.first_name, C.last_name
    HAVING SUM(CASE WHEN F.title = 'ANGELS LIFE' THEN 1 ELSE 0 END) = 0;
    

    【讨论】:

    • 谢谢!曾考虑过 HAVING 但认为我遇到了与 WHERE 相同的问题。重新定义结果然后过滤它的绝佳解决方案。再次感谢您!
    【解决方案2】:

    我会推荐带有相关子查询的not exists。在我看来,这就像您所要求的简单而直接的措辞:

    select c.*
    from customer c
    where not exists (
        select 1
        from rental r
        inner join inventory i on i.inventory_id = r.inventory_id
        inner join film f on f.film_id = i.film_id
        where f.title = 'ANGELS LIFE' and r.customer_id = c.customer_id
    )
    

    【讨论】:

    • 谢谢!两种方法都试过了,学到了新东西。你介意简单解释一下 select 1 在这里做什么而不是 select * ?
    • @HarryH247: exists 只检查子查询是否返回 something,不管有多少行或它们的内容。所以我们只使用select 1 - 这是一个约定,它很可能是select 0select *select null,这并不重要。
    • 感谢您的快速回复。刚刚玩了一下存在,绝对是我会读到的东西。感谢您抽出宝贵时间回复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 2020-03-22
    • 2022-01-08
    • 2015-08-14
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多