【问题标题】:SQL Server - Behaviour of ROW_NUMBER Partition by Null ValueSQL Server - 按空值划分的 ROW_NUMBER 分区的行为
【发布时间】:2017-02-01 00:15:57
【问题描述】:

我发现这种行为非常奇怪且违反直觉。 (即使是 SQL)。

set ansi_nulls off
go
;with sampledata(Value, CanBeNull) as
(
  select 1, 1
  union 
  select 2, 2
  union 
  select 3, null
  union 
  select 4, null
  union 
  select 5, null
  union 
  select 6, null
)
select ROW_NUMBER() over(partition by CanBeNull order by      value) 'RowNumber',* from sampledata

返回

1   3   NULL
2   4   NULL
3   5   NULL
4   6   NULL
1   1   1
1   2   2

这意味着为了计算行号,所有空值都被视为同一组的一部分。 SET ANSI_NULLLS 是打开还是关闭都没有关系。 但是由于根据定义,null 是完全未知的,那么如何将 null 像这样组合在一起呢?据说,为了将苹果和橙子、负 1 的平方根和量子黑洞或任何可以有意义地排序的东西按顺序排列。一个小实验表明,第一列用于生成排名顺序为

  select 1, '1'
  union 
  select 2, '2'
  union 
  select 5, null
  union 
  select 6, null
  union
  select 3, null
  union 
  select 4, null

生成相同的值。这具有重大影响,导致我正在处理的遗留代码出现问题。这是预期的行为吗?除了用唯一值替换 select 查询中的 null 之外,还有什么方法可以缓解它?

我预期的结果会是

1   3   NULL
1   4   NULL
1   5   NULL
1   6   NULL
1   1   1
1   2   2

使用 Dense_Rank() 没有区别。

【问题讨论】:

  • PARTITION BY 构建组,这不是一致的吗? GROUP BY 的作用与 SQL:2003 标准中记录的相同。 Read
  • 阅读。但是一个组在组内没有固有的顺序 - 分区确实会创建这样的顺序,因此根本不同

标签: sql-server null row-number


【解决方案1】:

哟。

因此,当 T-SQL 处理谓词中的 NULL 时,它使用三元逻辑(TRUE、FALSE 或 UNKNOWN)并显示您所声明的预期从查询中得到的行为。但是,在对值进行分组时,T-SQL 将 NULL 视为一组。因此,您的查询会将 NULL 组合在一起并开始为该窗口中的行编号。

对于您说希望看到的结果,此查询应该可以工作...

WITH sampledata (Value, CanBeNull)
AS
(
    SELECT 1, 1
    UNION
    SELECT 2, 2
    UNION
    SELECT 3, NULL
    UNION
    SELECT 4, NULL
    UNION
    SELECT 5, NULL
    UNION
    SELECT 6, NULL
)
SELECT
    DENSE_RANK() OVER (PARTITION BY CanBeNull ORDER BY CASE WHEN CanBeNull IS NOT NULL THEN value END ASC) as RowNumber
    ,Value
    ,CanBeNull
FROM sampledata

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-31
    • 2018-09-16
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 1970-01-01
    相关资源
    最近更新 更多