2016-09-23 7 views
1

이 동작은 매우 이상하고 반 직관적입니다. (SQL의 경우조차도). 널 모든 행 번호를 계산하기 위해 동일한 그룹의 일부로서 취급되는 것을 의미SQL Server - Null 값에 의한 ROW_NUMBER 파티션 동작

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

를 반환

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 

. 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 

는 같은 값을 생성 같은 순위를 생성하기 위해 사용되는 것을 의미한다. 이것은 내가 다루고있는 레거시 코드에서 문제를 일으키는 중요한 의미를 가지고있다. 이것은 예상되는 동작이며 선택 쿼리에서 null을 고유 한 값으로 바꾸는 것 이외의 다른 방법으로 완화 할 수 있습니까? 내가 기대했던 것

결과는 DENSE_RANK()를 차이가 없습니다 사용

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

을했을 것이다.

+0

'파티션 BY' 그래서, 그룹을 빌드가 일치하지 않습니다? 'GROUP BY'는 SQL : 2003 표준에 문서화 된 것과 동일합니다. [읽기] (https://technet.microsoft.com/en-us/library/ms187007 (v = sql.90) .aspx) –

+0

읽어보십시오. 그러나 그룹에는 그룹 내에서 고유 한 순서가 없습니다. 파티션은 이러한 순서를 만들고 그 자체로 근본적으로 다릅니다. – SimonN

답변

0

요.

그래서 T-SQL이 술어에서 NULL을 처리 할 때 3 진 논리 (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