2017-11-01 1 views
0

일부 데이터에 대해 순위 집합을 만들려면 DENSE_RANK() OVER PARTITION을 사용하려고합니다. 데이터는 날짜, 날짜 및 상태 순으로 정렬됩니다. 아래에 순위를 매기는 데 필요한 날짜 및 시간이 원하는 순위 출력입니다.DENSE_RANK() 또는 ROW_NUMBER() - 그룹을 만들려면

enter image description here

나는 다양한 DENSE_RANK 및 ROW_NUMBER 조합을 사용한 적이 있지만, 올바른 그룹을 얻을 수 없었다. 내가 원하는 것을 순위 매기는 것이 가능합니까?

+0

https://senseful.github.io/text-table/cr 스크린 샷을 사용하는 대신 텍스트 테이블을 작성하십시오. – SqlZim

답변

1
이전 ctstatusctstatus을 비교 lag()case 표현을 사용

, 다른 반환 1. 이것은 사람과 사람의 순위를 partition by에서 절로 이동하지 않을 경우 순위를 재설정하려고한다고 가정합니다. 그런 다음 누계로 sum() over()을 사용하여 rnk으로 지정하십시오.

;with cte as (
    select t.* 
    /* compare ctstatus with previous ctstatus, when different return by 1 */ 
    , inc = case when ctstatus = lag(ctstatus) over (
     partition by 
      description -- for each person 
     , atdate --for each day ? 
     order by atdatetime 
    ) then 0 else 1 end 
    from t 
) 
select 
    atdatetime 
    , atdate 
    , atext 
    , description 
    , ctstatus 
    , rnk = sum(inc) over (partition by description, atdate order by atdatetime) 
from cte; 
0

귀하의 설명 및 샘플 데이터를 기반으로 무엇을 그룹화할지 또는 분할 할지를 아는 것은 불가능하므로 지금 당장이 부분을 무시하고 있습니다. 즉, 여기에 SUM() OVER 창 집계를 사용하여이 작업을 수행 할 수 있습니다.

샘플 데이터

if object_id('tempdb..#x') is not null drop table #x; 

create table #x 
(
    ATDATETIME datetime, 
    ATDATE date, 
    ATEXT varchar(10), 
    CTSTATUS varchar(30) 
); 
create clustered index cl_x on #x(ATDATETIME); -- for a sort-free execution plan 

insert #x values 
(getdate()-1.90, cast(getdate()-1.90 as date), 1397, 'BK tomorrow...'), 
(getdate()-1.85, cast(getdate()-1.85 as date), 1397, 'AVAILABLE'), 
(getdate()-1.83, cast(getdate()-1.83 as date), 1397, 'AVAILABLE'), 
(getdate()-1.81, cast(getdate()-1.81 as date), 1397, 'AVAILABLE'), 
(getdate()-1.75, cast(getdate()-1.75 as date), 1397, 'AVAILABLE'), 
(getdate()-1.71, cast(getdate()-1.71 as date), 1397, 'Went away'), 
(getdate()-1.67, cast(getdate()-1.67 as date), 1397, 'AVAILABLE'), 
(getdate()-1.63, cast(getdate()-1.63 as date), 1397, 'AVAILABLE'), 
(getdate()-1.60, cast(getdate()-1.60 as date), 1397, 'AVAILABLE'), 
(getdate()-1.56, cast(getdate()-1.56 as date), 1397, 'AVAILABLE'), 
(getdate()-1.55, cast(getdate()-1.55 as date), 1397, 'Snuck out for beer'), 
(getdate()-1.50, cast(getdate()-1.50 as date), 1397, 'AVAILABLE'), 
(getdate()-1.46, cast(getdate()-1.46 as date), 1397, 'AVAILABLE'); 

솔루션

select ATDATETIME, ATDATE, ATEXT, CTSTATUS, RNK = 
    SUM(IIF(CTSTATUS = 'AVAILABLE' AND CTSTATUS_LAG1 = 'AVAILABLE',0,1)) 
    OVER (ORDER BY ATDATETIME) 
from 
(
    select *, CTSTATUS_LAG1 = LAG(CTSTATUS, 1) OVER (ORDER BY ATDATETIME) 
    from #x 
) tlag; 

결과

ATDATETIME    ATDATE  ATEXT  CTSTATUS      RNK 
----------------------- ---------- ---------- ------------------------------ ----------- 
2017-10-30 14:00:11.990 2017-10-30 1397  BK tomorrow...     1 
2017-10-30 15:12:11.990 2017-10-30 1397  AVAILABLE      2 
2017-10-30 15:40:59.990 2017-10-30 1397  AVAILABLE      2 
2017-10-30 16:09:47.990 2017-10-30 1397  AVAILABLE      2 
2017-10-30 17:36:11.990 2017-10-30 1397  AVAILABLE      2 
2017-10-30 18:33:47.990 2017-10-30 1397  Went away      3 
2017-10-30 19:31:23.990 2017-10-30 1397  AVAILABLE      4 
2017-10-30 20:28:59.990 2017-10-30 1397  AVAILABLE      4 
2017-10-30 21:12:11.990 2017-10-30 1397  AVAILABLE      4 
2017-10-30 22:09:47.990 2017-10-30 1397  AVAILABLE      4 
2017-10-30 22:24:11.990 2017-10-30 1397  Snuck out for beer    5 
2017-10-30 23:36:11.990 2017-10-30 1397  AVAILABLE      6 
2017-10-31 00:33:47.990 2017-10-31 1397  AVAILABLE      6 
사용할 수