选择描述字段而不将其包含在 GROUP BY 子句中时 GROUP BY id 的最佳方法

Posted

技术标签:

【中文标题】选择描述字段而不将其包含在 GROUP BY 子句中时 GROUP BY id 的最佳方法【英文标题】:Best way to GROUP BY id while SELECTing a description field without including it in the GROUP BY clause 【发布时间】:2021-10-11 13:30:37 【问题描述】:

我有两张桌子:

公司表

Id,
CompanyName

销售表:

Id,
CompanyId,
Date,
Value

我需要按日期和公司对销售额进行分组,并像这样显示:

CompanyId  CompanyName           Date        Value
---------  --------------------  ----------  --------
        1  Company 1             2021-10-01  2832.98
        2  Company 2             2021-10-01  8112.81
        1  Company 1             2021-10-02  2182.12
        2  Company 2             2021-10-02  3521.11

我知道我可以通过这个轻松实现它

SELECT s.CompanyId, c.CompanyName, s.Date, SUM(s.Value) FROM Sale s
JOIN Company c on s.CompanyId = c.Id
GROUP BY s.Date, s.CompanyId, c.CompanyName

问题是当我在 GROUP BY 子句中包含 CompanyName 时,它会慢一个数量级。我也许可以通过添加一个新索引来规避它,但现在这不是一个选项。

我能够使用此查询使其运行得更快

SELECT 
    s.CompanyId, 
    (SELECT CompanyName FROM Company WHERE Id = s.CompanyId) as CompanyName
    s.Date, 
    SUM(s.Value) 
FROM Sale s
GROUP BY s.Date, s.CompanyId

但我想知道是否有更快/更好的方法。没有 CompanyName 的 group by 在 2 秒内运行,如果我将 CompanyName 添加到 GROUP BY 它会为查询增加 20 秒。使用我列出的最后一个查询,它会在大约 5 秒内运行。

【问题讨论】:

没有关于索引的信息和查询计划(您可以通过brentozar.com/pastetheplan 分享)我们无法帮助您。如果没有更好的索引,您不可能比现有的性能提高更多 您可以尝试将 行目标 添加到子查询中,这可能会有所帮助,具体取决于当前的执行计划。 【参考方案1】:

将名称的查找推迟到分组之后? 未测试...

select i.CompanyId,c.CompanyName,i.Date,i.Value
From Company c join(
SELECT 
    s.CompanyId, 
    s.Date, 
    SUM(s.Value) as [Value]
FROM Sale s
GROUP BY s.Date, s.CompanyId) i
on i.CompanyId = c.CompanyId

【讨论】:

这可能与子查询选项具有相同的性能。引擎确实通常足够聪明,可以在两者之间转换 从这里很难分辨,你希望引擎能把它弄清楚,因为它有点明显。索引是唯一真正的解决方案。 我也认为这应该产生相同的速度,但实际上要快一点。我的查询比我向您展示的要复杂得多,我简化了它以专注于问题。我会接受你的回答,谢谢。 既然你已经有 CompanyId - 你不能只使用 MAX(c.CompanyName) 吗?

以上是关于选择描述字段而不将其包含在 GROUP BY 子句中时 GROUP BY id 的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

列“在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中”]]

having是否依赖于group by

选择列表中的无效表达式(不包含在聚合函数或 GROUP BY 子句中)

列“在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中”

列的原因在选择列表中无效,因为它不包含在聚合函数或 GROUP BY 子句中[重复]

SQL:选择列表中的列无效,因为它不包含在聚合函数或 GROUP BY 子句中[关闭]