【问题标题】:Separate subselects to get multiple counts?单独的子选择以获得多个计数?
【发布时间】:2018-09-17 15:24:02
【问题描述】:

我有这个问题:

SELECT  
(SELECT COUNT(media_id) FROM likes WHERE like_state = true AND media_id = ?) AS likes, 
(SELECT COUNT(media_id) FROM likes WHERE like_state = false AND media_id = ?) AS dislikes, 
(SELECT media_views FROM media_thumbnail WHERE media_id = ?) AS views;

它工作正常,但我不确定这是否是最好的方法。有什么建议吗?

我认为这不需要任何解释,但是...它计算有多少喜欢或不喜欢在 like_statetrue = 喜欢,false = 不喜欢)的函数中,并返回视图相关视频的计数。

【问题讨论】:

  • 您能对该查询运行解释分析吗?
  • 在什么意义上“最好的方式”?此查询是否有任何问题,例如运行速度太慢?
  • 不,我不只是想知道是否有其他方法。什么是解释分析?
  • 显示数据类型和约束的 Postgres 版本和表定义可能是相关的。

标签: sql postgresql count cross-join


【解决方案1】:

在表likes 上使用两个计数的单个SELECT 肯定比两个单独的SELECT 更快:

SELECT COUNT(    like_state OR NULL) AS likes
     , COUNT(NOT like_state OR NULL) AS dislikes
     ,(SELECT media_views FROM media_thumbnail WHERE media_id = ?) AS views
FROM   likes
WHERE  media_id = ?;

此查询与不相关的子查询之间存在极端情况差异,您的原始查询与两个隐式 CROSS JOIN(@987654332 中的逗号 , @list 几乎等同于 CROSS JOIN) 以及 Gordon 对最后一个子查询的回答为 CROSS JOIN

前两个子查询总是返回一行,所以CROSS JOIN 不能消除结果。 但是第三个查询可能在表media_thumbnail 中找不到给定的media_id 并返回no row。一个CROSS JOIN 会导致整个查询的no row

SELECT 列表中带有子查询的我的查询将 no row 转换为空值,并且仍然返回结果行。 LEFT JOIN ... ON true 也可以达到同样的效果:

SELECT 中的子查询如果返回多于一行,则会引发异常 - 如果 media_thumbnail.media_id 定义为 UNIQUEPRIMARY KEY,则不会发生这种情况,并且可能不应该发生无论如何。

关于条件计数:

使用FILTER 子句的语法简洁明了:

SELECT COUNT(*) FILTER (WHERE     like_state) AS likes
     , COUNT(*) FILTER (WHERE NOT like_state) AS dislikes
...

有点冗长,但可能更容易阅读。性能基本相同。

【讨论】:

    【解决方案2】:

    您的查询很好,尽管我更倾向于将其写成:

    SELECT SUM( (l.like_state = true)::int ) as likes,
           SUM( (l.like_status = false)::int ) as dislikes,
           MAX(mt.media_views) as media_views
    FROM likes l CROSS JOIN
         (SELECT media_views FROM media_thumbnail WHERE media_id = ?
         ) mt
    WHERE l.media_id = ?;
    

    这样可以节省一次扫描likes 表的开销。

    【讨论】:

    • 你能解释一下为什么要使用交叉连接吗?
    • 它说:“mt.media_views”列应该出现在 GROUP BY 子句中或用于聚合函数中。我不知道如何解决它。
    • @RobertRocha 。 . .它使用cross join 引入具有单行的结果集。
    猜你喜欢
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 2020-06-29
    • 1970-01-01
    相关资源
    最近更新 更多