2016-09-23 121 views
1

我發現這種行爲非常奇怪並且違反直覺。 (即使對於SQL)。SQL Server - ROW_NUMBER分區空值的行爲

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值替換select查詢中的空值之外,是否有任何減輕它的方法?

我本來期望的結果將是

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

使用DENSE_RANK()沒有什麼區別。

+0

'PARTITION BY'建立羣體,所以是不是一致的? 「GROUP BY」的功能與SQL:2003標準中記錄的相同。 [閱讀](https://technet.microsoft.com/en-us/library/ms187007(v = sql.90).aspx) –

+0

閱讀它。但是一個小組在組內並沒有內在的秩序 - 劃分是通過創建這樣一個秩序來實現的,因此根本上是不同的 – SimonN

回答

0

呦。

因此,當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