【问题标题】:SQL Subqueries within Subqueries子查询中的 SQL 子查询
【发布时间】:2014-07-09 04:58:58
【问题描述】:

我有一个带有 Tunes 表的音乐数据库。每个 Tunes 记录都包含一个 ArtistIDRating

我想要做的是检索所有唯一的 ArtistID 字段(很简单)加上一列,表明每个艺术家的曲调的一些评级值是非零的。

我可以进行查询以返回 0 或 1,以确定是否有任何 Artists 曲调未被评级如下:

SELECT COUNT() FROM ( 
    SELECT ID FROM Tune WHERE ArtistID=a AND Rating < 1 LIMIT 1 
)

上述查询将返回“SomeUnrated”真或假(1 或 0)值。

而且.. 我可以进行查询以返回 Tunes 表中的所有唯一艺术家 ID:

SELECT DISTINCT Artist.ID, Artist.Name
FROM Artist JOIN Tune ON Artist.ID=Tune.ArtistID

如何组合这两个查询,以便我得到如下值列表:

Artist.ID  Artist.Name  SomeUnrated

我正在使用 SQLite。这是“相关”子查询的示例吗?

【问题讨论】:

    标签: sql sqlite subquery correlated-subquery


    【解决方案1】:

    如果您未评级的值是null(正确的数据库设计会规定),那么您可以总结您的评级。一个数字 + null = null。所以你会得到你的错误。

    Select 
      Artist.ID, 
      sum(rating) as SomeUnrated
    from
      Artist 
      join Tune on Artist.ID = Tune.ArtistID
    group by
      Artist.ID
    

    这是fiddle

    我确实推荐 null 作为未评级值,如果您仍然想要零,可以将 null 合并为 0

    *我把名字忘了是因为我在模式中忘记了它,只需将它添加到选择和分组依据

    编辑:

    我相信这是基于cmets的解决方案。

    SELECT
      Artist.ID, 
      Artist.Name,
      SUM(Tune.Rating) AS SomeUnrated,
      COUNT()
    FROM
      Artist 
      JOIN Tune ON Artist.ID = Tune.ArtistID
    GROUP BY
      Artist.ID
    

    【讨论】:

    • 不,正如所写,这将找到 single artist 的 SUM(rating)。 OP 似乎在表明是否有任何未评级的艺术家根本
    • @AndriyM,我对 OP 问题的解释是,他希望能够区分一个艺术家对他的所有曲调都进行了评级,还是只对他的部分进行了评级。也许SomeUnrated 名称具有误导性
    • @paqogomez:谢谢 - 它给了我其他的想法,但我担心它不会给出所需的结果。 “评级”可以是 +ve、0 或 -ve。如果 SUM(Rating) 等于属于 Artist.ID 的 Tune 记录的总数,则您的解决方案将起作用的唯一方法是返回 1 或 0。我可以通过编程或分步来解决这个问题,但我确实需要一条 SQL 语句,而且我的 SQL 不是那么热门。 :)
    • @SparkyNZ +ve?那是一个字符串值吗?您可以修改小提琴以提供正确的架构吗?
    • @paqogomez:不,它是一个整数。 +ve 值是“喜欢”的曲调,-ve 值是讨厌的曲调,零是中性(未评级)。
    【解决方案2】:

    作为最终查询的第一步,您可以将 DISTINCT 替换为 GROUP BY:

    SELECT
        Artist.ID,
        Artist.Name
    FROM Artist
    JOIN Tune ON Artist.ID = Tune.ArtistID
    GROUP BY Artist.ID, Artist.Name;
    

    结果将与 DISTINCT 相同,但现在您可以将其他信息合并到查询中。您不需要将其作为子查询,但您需要一个条件来配合它,所以...

    SELECT
        Artist.ID,
        Artist.Name,
        COUNT(DISTINCT CASE WHEN Rating < 1 THEN 1 END) AS SomeUnrated
    FROM Artist
    JOIN Tune ON Artist.ID = Tune.ArtistID
    GROUP BY Artist.ID, Artist.Name;
    

    或者,您可以使用MAX() 计算相同的结果:

    SELECT
        Artist.ID,
        Artist.Name,
        MAX(CASE WHEN Rating < 1 THEN 1 ELSE 0 END) AS SomeUnrated
    FROM Artist
    JOIN Tune ON Artist.ID = Tune.ArtistID
    GROUP BY Artist.ID, Artist.Name;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-08
      • 2010-09-17
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多