2011-12-15 5 views
5

Mam tabelę z dwiema kolumnami: identyfikator pary i liczbę "znaków" dla tej pary . Chciałbym uzyskać wynik, który zawiera liczbę par, które mają x znaków lub więcej dla każdej z wartości x. Więc moje wejście wygląda następująco:Zliczanie liczby wierszy o wartości większej lub równej wartości z innej kolumny w SQL

 
| couple_id | num_marks | 
|-----------+-----------| 
|   9 |   7 | 
|   6 |   6 | 
|   8 |   6 | 
|   2 |   5 | 
|   3 |   4 | 
|   5 |   4 | 
|   1 |   3 | 
|   4 |   3 | 
|  10 |   2 | 
|   7 |   1 | 

I chciałbym, aby uzyskać wynik:

 
| num_marks | num_couples | 
|-----------+-------------| 
|   7 | 1   | 
|   6 | 3   | 
|   5 | 4   | 
|   4 | 6   | 
|   3 | 8   | 
|   2 | 9   | 
|   1 | 10   | 

Tj było 1 para z 7 lub więcej znakami, 3 pary z 6 lub więcej znakami, 4 pary z 5 lub więcej znakami, itp. Udało mi się wymyślić zapytanie do zwrócić liczbę par z dokładnien znaki:

SELECT num_marks, 
     count(couple_id) AS num_couples 
    FROM table_name 
    GROUP BY num_marks 
    ORDER BY num_marks DESC; 

co daje:

 
| num_marks | num_couples | 
|-----------+-------------| 
|   7 |   1 | 
|   6 |   2 | 
|   5 |   1 | 
|   4 |   2 | 
|   3 |   2 | 
|   2 |   1 | 
|   1 |   1 | 

Ie było 1 para z 7 znakami, 2 pary z 6 znakami, 1 z 5 itd. Czy jest tam wygodnie skuteczny sposób na zsumowanie wartości każdego wiersza z tymi powyżej ? Mogę to zrobić na poziomie aplikacji, ale wydaje mi się, że to coś, co naprawdę należy do bazy danych.

Odpowiedz

5

To może nie być szczególnie skuteczne, ale należy to zadanie:

SELECT t1.num_marks,  
    (SELECT count(t2.couple_id) 
    FROM table_name t2 
    WHERE t2.num_marks >= t1.num_marks 
    ) AS num_couples 
FROM table_name t1 
GROUP BY t1.num_marks 
ORDER BY t1.num_marks DESC; 

Edit: Można użyć sub query w select, z, gdzie grupa przez i posiadające klauzule zapytania , a jeśli odwołasz się do głównej/zewnętrznej "kwerendy", wówczas oceni podzapytanie dla każdego wiersza, wtedy jest to znane jako correlated subquery. (Stąd zastrzeżenie dotyczące wydajności):

Zgodnie z odpowiedzią Damiena, można również użyć CTE - CTE może poprawić czytelność, a także ułatwić rekursję i samonakładanie się IMO.

Podzapytania AFAIK są obsługiwane w większości SQL-ów.

+0

To szalenie genialne! Nie wiedziałem, że możesz mieć kolumny "SELECT" jako kolumny. Czy to standardowy SQL, który działałby na przykład SQLite i Postgres? Poza tym moja nazwa 'table_name' nie jest tak naprawdę tabelą, jest to wielka tracka' SELECT' na własną rękę; czy to by złamało? – haxney

+1

@haxney - Edytowałem - tak, możesz zastąpić nazwa_tabeli innym zapytaniem, musisz to zrobić, aby użyć jej do wyboru zewnętrznego. – StuartLC

4

Można użyć funkcji RANK() wypracować gdzie każdy wynik plasuje się, a potem po prostu dodać liczbę wiązanej wyników na tej rangi:

create table #T (couple_id int,num_marks int) 
insert into #T (couple_id,num_marks) 
select 9 ,   7 union all 
select 6 ,   6 union all 
select 8 ,   6 union all 
select 2 ,   5 union all 
select 3 ,   4 union all 
select 5 ,   4 union all 
select 1 ,   3 union all 
select 4 ,   3 union all 
select 10 ,   2 union all 
select 7 ,   1 

;with Ranked as (
    select num_marks,RANK() OVER (ORDER BY num_marks desc) as rk from #T 
) 
select num_marks,rk + COUNT(*) -1 as Result from Ranked 
group by num_marks,rk 

Daje:

num_marks Result 
----------- -------------------- 
7   1 
6   3 
5   4 
4   6 
3   8 
2   9 
1   10 

(7 row(s) affected) 

(Oczywiście, jeśli potrzebujesz wyników w konkretnym zamówieniu, nie zapomnij dodać klauzuli ORDER BY - powyższe zamówienie jest po prostu szczęśliwym wypadkiem)