【问题标题】:Select Records With Only One SPECIFIC Value In A Column Where Multiple Are Possible using Set Operations在列中选择只有一个特定值的记录,使用集合操作可能有多个
【发布时间】:2020-08-06 15:44:28
【问题描述】:

您好,我在对组成的数据集练习一些 SQL 查询时,真的很想解决这个特殊的问题。

给定以下表格:

  • 电影(MovieID,Title,ProducerName)
  • DVD(MovieID,StoreID)
  • 商店(商店ID,商店名称)

我不知道如何从制作人“BBC”(ProducerName = BBC)中检索只有电影的商店名称。我想尝试在连接中使用子查询和设置操作。

我主要靠猜测,因为我无法在任何地方测试查询,但非常感谢任何帮助。有没有更好的方法可以在不使用连接的情况下做到这一点?

select distinct(StoreName)
from STORE
where not exists (
(select distinct(Title)
from MOVIE JOIN DVDs
where DVD.StoreID == STORE.StoreID)
except
(select distinct(Title)
from MOVIE 
where producerName = ‘BBC’))

【问题讨论】:

  • 与您的问题无关,但是:distinct 不是函数。它始终适用于选择列表中的所有列。用括号括住其中一列不会改变任何东西并且是无用的。 distinct (a),bdistinct a,(b)distinct a,b 相同。在这种情况下,EXISTS 条件的子选择中的 distinct 是完全没有必要的

标签: sql postgresql join select group-by


【解决方案1】:

我会使用not exists 如下:

select s.*
from store s
where not exists (
    select 1 
    from dvd d
    inner join movie m on m.movieID = d.movieID
    where m.producerName <> 'BBC' and d.storeID = s.storeID
)

这会选择没有来自 BBC 以外的制片人的电影的商店。您可以通过添加另一个exists 条件来更具体:

select s.*
from store s
where 
    exists (
        select 1 
        from dvd d
        inner join movie m on m.movieID = d.movieID
        where m.producerName = 'BBC' and d.storeID = s.storeID
    )
    and not exists (
        select 1 
        from dvd d
        inner join movie m on m.movieID = d.movieID
        where m.producerName <> 'BBC' and d.storeID = s.storeID
    )

另一个选项是聚合:

select s.storeID, s.storeName
from store s
inner join dvd d on d.storeID = s.storeID
inner join movie m on m.movieID = d.movieID
group by s.storeID, s.storeName
having bool_and(m.producerName = 'BBC')

【讨论】:

    【解决方案2】:

    如果你不想使用任何joins,你可以这样做:

    select s.*
    from store s
    where not exists (select 1
                      from (select dvd.*,
                                   (select m.ProducerName
                                    from movie m
                                    where m.movieId = dvd.movieId
                                   ) as ProducerName
                            from dvd
                           ) dvd
                      where dvd.ProducerName <> 'BBC' and
                            dvd.storeId = s.storeId
                     );
    

    你也可以在下一个exists 子句:

    select s.*
    from store s
    where not exists (select 1
                      from dvd
                      where dvd.storeId = s.storeId and
                            exists (select 1
                                    from movie m
                                    where m.movieId = dvd.movieId and
                                          dvd.ProducerName <> 'BBC'
                                   )
                     );
    

    但是,我发现 exists/not exists(或 in/not in 的等价物)的这种嵌套组合令人费解——比等价的join 版本更难理解。

    【讨论】:

      猜你喜欢
      • 2014-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-08
      • 1970-01-01
      • 1970-01-01
      • 2018-02-23
      • 1970-01-01
      相关资源
      最近更新 更多