我发现这种行为非常奇怪且违反直觉。 (即使是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是完全未知的,那么如何将空值组合在一起呢?据说,为了按照等级顺序放置东西,苹果和橙子以及负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()没有任何区别。
答案 0 :(得分: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