单独的子选择以获得多个计数?

Separate subselects to get multiple counts?

我有这个查询:

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_state 函数中有多少喜欢或不喜欢(true = 喜欢,false = 不喜欢)和 returns 相关视频的观看次数。

你的查询很好,虽然我更倾向于把它写成:

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 table 的开销。

在 table 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 = ?;

此查询与不相关的子查询之间存在 corner-case 差异,您的原始查询具有两个隐式 CROSS JOINFROM 列表中的逗号 , 几乎与 CROSS JOIN 相同)以及戈登对最后一个子查询的 CROSS JOIN 的回答。

前两个子查询总是return一行,所以一个CROSS JOIN不能消去结果。 但是第三个查询可能找不到给定的 media_id in table media_thumbnail and return no rowCROSS JOIN 导致整个查询 no row

我在 SELECT 列表中使用子查询的查询将 无行 转换为空值,并且仍然 return 是一个结果行。 LEFT JOIN ... ON true:

也可以达到同样的效果

如果 return 超过一行,我在 SELECT 中的子查询会引发异常 - 如果 media_thumbnail.media_id 定义为 UNIQUE 或 [=30,则不会发生这种情况=],可能不应该在任何情况下都不会发生。

关于条件计数:

漂亮干净的语法将带有 FILTER 子句:

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

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