2017-01-31 43 views
5

Oto co moje dane wygląda następująco:DENSE_RANK() bez powielania

| col1 | col2 | denserank | whatiwant | 
|------|------|-----------|-----------| 
| 1 | 1 | 1   | 1   | 
| 2 | 1 | 1   | 1   | 
| 3 | 2 | 2   | 2   | 
| 4 | 2 | 2   | 2   | 
| 5 | 1 | 1   | 3   | 
| 6 | 2 | 2   | 4   | 
| 7 | 2 | 2   | 4   | 
| 8 | 3 | 3   | 5   | 

Oto zapytanie mam tak daleko:

SELECT col1, col2, DENSE_RANK() OVER (ORDER BY COL2) AS [denserank] 
FROM [table1] 
ORDER BY [col1] asc 

Co chciałbym osiągnąć to dla mojego denserank kolumnie przyrost za każdym razem, gdy następuje zmiana w wartości col2 (nawet jeśli sama wartość jest ponownie używana). Nie mogę faktycznie zamówić przez kolumnę, w której mam gęstość, więc to nie zadziała). Zobacz kolumnę whatiwant dla przykładu.

Czy jest jakiś sposób osiągnięcia tego celu przy pomocy DENSE_RANK()? Czy istnieje alternatywa?

Odpowiedz

4

Spróbuj tego wykorzystujące funkcje okna:

with t(col1 ,col2) as (
select 1 , 1 union all 
select 2 , 1 union all 
select 3 , 2 union all 
select 4 , 2 union all 
select 5 , 1 union all 
select 6 , 2 union all 
select 7 , 2 union all 
select 8 , 3 
) 
select t.col1, 
    t.col2, 
    sum(x) over (
     order by col1 
     ) whatyouwant 
from (
    select t.*, 
     case 
      when col2 = lag(col2) over (
        order by col1 
        ) 
       then 0 
      else 1 
      end x 
    from t 
    ) t 
order by col1; 

produkuje:

enter image description here

To nie pojedynczy stół czytać i tworzy grupę kolejnych równych wartościach cOL2 w porządku rosnącym z col1, a następnie znajduje na tym gęste miejsce.

  • x: wartość Przypisanie 0 jeśli kolumna2 poprzedniego rzędu jest taki sam jak col2 tym samym wierszu (w celu zwiększenia col1) poza 1
  • : tworzenie grup jednakowych wartościach col2 w celu zwiększenia col1 wykonując przyrostowa suma wartości x wygenerowana w ostatnim kroku i to jest twój wynik.
+0

Właśnie skopiowałeś mój kod w inny sposób niż nie jest to uczciwe. Wcześniej kod był tak inny –

1

Wydaje mi się, że jest to możliwe w czystym SQL, wykorzystującym luki i triki wysp, ale ścieżka najmniejszego oporu może polegać na użyciu zmiennej sesji połączonej z LAG(), aby śledzić, kiedy obliczona gęsta ranga zmienia wartość. W poniższym zapytaniu, używam @a śledzić zmiany w gęstej rangi, a kiedy zmienia zmienna ta jest zwiększana o 1.

DECLARE @a int 
SET @a = 1 
SELECT t.col1, 
     t.col2, 
     t.denserank, 
     @a = CASE WHEN LAG(t.denserank, 1, 1) OVER (ORDER BY t.col1) = t.denserank 
       THEN @a 
       ELSE @a+1 END AS [whatiwant] 
FROM 
(
    SELECT col1, col2, DENSE_RANK() OVER (ORDER BY COL2) AS [denserank] 
    FROM [table1] 
) t 
ORDER BY t.col1 
4

zrobiłbym to z rekurencyjnej CTE tak:

declare @Dept table (col1 integer, col2 integer) 

insert into @Dept values(1, 1),(2, 1),(3, 2),(4, 2),(5, 1),(6, 2),(7, 2),(8, 3) 

;with a as (
select col1, col2, 
ROW_NUMBER() over (order by col1) as rn 
from @Dept), 
s as 
(select col1, col2, rn, 1 as dr from a where rn=1 
union all 
select a.col1, a.col2, a.rn, case when a.col2=s.col2 then s.dr else s.dr+1 end as dr 
from a inner join s on a.rn=s.rn+1) 
col1, col2, dr from s 

result: 

col1  col2  dr 
----------- ----------- ----------- 
1   1   1 
2   1   1 
3   2   2 
4   2   2 
5   1   3 
6   2   4 
7   2   4 
8   3   5 

ROW_NUMBER jest wymagane tylko w przypadku, gdy col1 wartości nie są sekwencyjne.Jeśli są one można użyć rekurencyjnej CTE razu

3

Oto jeden ze sposobów korzystania SUM OVER(Order by) okno funkcję statystyczną

SELECT col1,Col2, 
     Sum(CASE WHEN a.prev_val = a.col2 THEN 0 ELSE 1 END) OVER(ORDER BY col1) AS whatiwant 
FROM (SELECT col1, 
       col2, 
       Lag(col2, 1)OVER(ORDER BY col1) AS prev_val 
     FROM Yourtable) a 
ORDER BY col1; 

Jak to działa:

LAG funkcja okno służy do znalezienia poprzedniego col2 dla każdego wiersza zamówionego przez col1

SUM OVER(Order by) spowoduje zwiększenie liczby y kiedy poprzedni col2 nie jest równy bieżącemu col2