【问题标题】:List or concatenate in SQL window function在 SQL 窗口函数中列出或连接
【发布时间】:2020-01-29 19:49:24
【问题描述】:

我团队的一个(对 SQL 相对较新)成员正在编写一个碰巧使用窗口函数的 SQL 查询。在审查后,我注意到他们的窗口功能是这样构建的:

COUNT(*) OVER(PARTITION BY Part1+Part2) AS A

我立即做了反馈,说应该是这样的:

COUNT(*) OVER(PARTITION BY Part1, Part2) AS A

Part1 和 Part2 都是 nvarchars。

然后我停下来反思,我实际上无法弄清楚为什么那会是错误的。据我所见,这实际上会产生相同的结果(确实如此)。除了在第一个查询的初始表扫描之后额外的计算标量步骤之外,实际执行计划几乎相同(这是查询成本的 0%)。 I/O 统计数据显示,第一个版本的逻辑读取次数减少了 5 次(12,665 到 12,670)。

那么除了编码约定之外,使用这两种形式是否有任何好处/坏处?在这种情况下这是否可以正常工作,但在某些情况下可能会产生不一致的结果?

【问题讨论】:

  • 如果零件是 (3,5)、(4,4) 和 (2,6) 怎么办?还是('2','12')('21','2')?此外,服务器必须在对数据进行分区之前提前计算所有连接,这对索引或外部查询的排序顺序没有任何好处

标签: sql sql-server tsql count window-functions


【解决方案1】:

这两个表达式都是有效的,但它们的作用不同。

考虑以下数据:

Part1    Part2
AB       C
A        BC

当用PARTITION BY Part1+Part2连接字符串时,两条记录属于同一个分区,而当使用PARTITION BY Part1, Part2时,它们将属于不同的分区。

所以问题实际上归结为:您的用例的正确分区标准是什么?通常,除非你在做一些花哨的事情,否则你想要PARTITION BY Part1, Part2。但这实际上必须根据您的实际用例从功能角度回答。

【讨论】:

  • 我怀疑第一个表达式也会导致性能不佳,因为服务器必须在分区之前计算所有值
  • 另外,如果 Part1 或 Part2 是 NULL,则连接结果将是 NULL,这可能是也可能不是预期结果
【解决方案2】:

PARTITION 表达式正是——一个表达式。因此,您可以在其中放置几乎任何形式的表达式,并使用该值对行进行分区。

在结果不一致方面,如果你有这种情况,你会遇到问题:

Part1    Part2    Part1 + Part2
'yummy'  'sushi'  'yummysushi'
'yumm'   'ysushi' 'yummysushi'

即使列具有不同的值,两行也会被视为同一分区的一部分。

就性能而言,我唯一的猜测是,如果您在这些特定列上设置了索引或任何分区方案,那么您可能会在那里得到改进。

最好的办法是使用您指定的第二种情况(Part1, Part2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2022-01-19
    相关资源
    最近更新 更多