何时在包含 JOIN 和聚合的 SQL 查询中使用 *?

Posted

技术标签:

【中文标题】何时在包含 JOIN 和聚合的 SQL 查询中使用 *?【英文标题】:When to Use * in SQL Query Containing JOINs & Aggregations? 【发布时间】:2020-08-10 15:07:26 【问题描述】:

问题

Web_events 表包含id,..., channel,account_id

accounts 表包含id, ..., sales_rep_id

sales_reps 表包含idname

给定上述表,编写一个 SQL 查询来确定特定 channelweb_events 表中用于 sales_reps 中每个名称的次数。您的最终表格应该包含三列 - sales_repschannel 的名称和出现次数。首先对出现次数最多的表格进行排序。

回答

SELECT s.name, w.channel, COUNT(*) num_events
FROM accounts a
JOIN web_events w
ON a.id = w.account_id
JOIN sales_reps s
ON s.id = a.sales_rep_id
GROUP BY s.name, w.channel
ORDER BY num_events DESC;

COUNT(*) 让我很困惑。我不明白 SQL 是如何计算出COUNT(*)COUNT(w.channel)。谁能澄清一下?

【问题讨论】:

count() 这样的聚合门函数会为您定义的每个组返回结果。 COUNT(*) 表示“计数行”,即组合在一起的行数。与COUNT(w.channel) 相同,但前提是w.channel 不能为NULL 基于Group By 子句。只是为了补充一点,在您的情况下,count(*) 可能与count(w.channel) 不同。您在组中也有s.name,这意味着count(*) 将根据s.namew.channel 的组合给出计数 【参考方案1】:

我不明白 SQL 是如何计算出 COUNT(*) 是 COUNT(w.channel)

COUNT() 是一个聚合函数,用于计算匹配条件的行数。事实上,一般COUNT(<expression>)(或特别是COUNT(column))计算表达式(或列)不是NULL的行数。

一般来说,以下完全做同样的事情:

COUNT(*) COUNT(1) COUNT(<primary key used on inner join>)

一般来说,我更喜欢COUNT(*),因为这是SQL 标准。我可以接受COUNT(1) 承认COUNT(*) 只是功能膨胀。但是,我认为没有理由使用第三个版本,因为它只是需要额外的输入。

除此之外,我发现新用户经常对这两种结构感到困惑:

COUNT(w.channel) COUNT(DISTINCT w.channel)

学习 SQL 的人通常认为第一个确实是第二个。出于这个原因,我建议坚持使用更简单的行数计数方法。然后,当您真的想产生计算唯一值的开销时使用COUNT(DISTINCT)COUNT(DISTINCT)COUNT() 更昂贵)。

【讨论】:

以上是关于何时在包含 JOIN 和聚合的 SQL 查询中使用 *?的主要内容,如果未能解决你的问题,请参考以下文章

T-SQL GROUP BY 也使用 JOIN、聚合和外部引用错误

clickhouse,数据查询与写入优化,分布式子查询优化,外部聚合/排序优化,基于JOIN引擎的优化,SQL优化案例,物化视图提速,查询优化常用经验法则,选择和主键不一样的排序键,数据入库优化(代码

在聚合表达式中使用包含时 sql 查询出错

用于聚合的 Spark 数据集或数据框

查询包含多个 JOIN 时访问 SQL 语法错误(缺少运算符)

SQL——连接查询聚合函数开窗函数