2010-06-17 8 views
5

Mam bazę danych badania z jedną kolumną dla każdego pytania i jeden wiersz dla każdej osoby, która odpowiada. Każde pytanie jest o wartości od 1 do 3.W SQL, jak mogę policzyć liczbę wartości w kolumnie, a następnie przestawić go tak, aby kolumna stała się wierszem?

Id Quality? Speed? 
-- ------- ----- 
1  3   1 
2  2   1 
3  2   3 
4  3   2 

Teraz trzeba wyświetlić wyniki jako jeden wiersz na pytanie, z kolumną dla każdej liczby odpowiedzi i wartość w każdej kolumnie oznacza liczbę odpowiedzi, które wykorzystały tę odpowiedź. Na koniec muszę obliczyć całkowity wynik, który jest liczbą 1 plus dwa razy liczbę 2 plus trzy razy liczbę trójek.

Question 1 2 3 Total 
-------- -- -- -- ----- 
Quality? 0 2 2 10 
Speed? 2 1 1 7 

Czy można to zrobić w zestawie SQL? Wiem, jak to zrobić za pomocą pętli w języku C# lub kursorów w SQL, ale staram się, aby działało w narzędzie raportowania, które nie obsługuje kursorów.

+0

Chcesz to zrobić w danym RDBMS? –

+0

Czy klawisze id reprezentują pojedyncze pytania lub poszczególnych użytkowników? – Kenneth

+0

jakie narzędzie do raportowania –

Odpowiedz

3

to daje co pytasz o:

SELECT 
    'quality' AS question, 
    SUM(CASE WHEN quality = 1 THEN 1 ELSE 0 END) AS [1], 
    SUM(CASE WHEN quality = 2 THEN 1 ELSE 0 END) AS [2], 
    SUM(CASE WHEN quality = 3 THEN 1 ELSE 0 END) AS [3], 
    SUM(quality) 
FROM 
    dbo.Answers 
UNION ALL 
SELECT 
    'speed' AS question, 
    SUM(CASE WHEN speed = 1 THEN 1 ELSE 0 END) AS [1], 
    SUM(CASE WHEN speed = 2 THEN 1 ELSE 0 END) AS [2], 
    SUM(CASE WHEN speed = 3 THEN 1 ELSE 0 END) AS [3], 
    SUM(speed) 
FROM 
    dbo.Answers 

Należy pamiętać jednak, że będzie to szybko balon miarę dodawania pytań lub nawet potencjalne odpowiedzi. Możesz być o wiele lepiej, jeśli znormalizowałeś nieco i miałeś tabelę odpowiedzi z wierszem dla każdej odpowiedzi z kodem pytającym lub identyfikatorem, zamiast umieszczać je jako kolumny w jednej tabeli. Zaczyna wyglądać trochę jak projekt pary podmiot-wartość, ale myślę, że jest na tyle inny, aby być przydatnym tutaj.

+0

To ma sens, dzięki! –

+0

Czy ten kod nie wymaga grupy według instrukcji? Do przechowywania danych - zgadzam się z sugerowaną normalizacją, ale gdy dochodzi do analizy, musisz napisać co najmniej widok typu arkusza kalkulacyjnego dla większości pakietów oprogramowania statystycznego. Chciałbym, aby udowodniono, że jest źle na ostatnim wyciągu ... –

+0

@ ran2 - Nie potrzebuje GROUP BY, ponieważ jest podsumowaniem całego stołu. Po jego normalizacji można uzyskać te same dane za pomocą podobnego zapytania, ale bez wszystkich UNION. Możesz także użyć PIVOT. –

1

Można również wykorzystać funkcje przechodzenia SQL 2005, aby osiągnąć to, co chcesz. W ten sposób nie musisz sztywno kodować żadnych pytań, jak w przypadku cross-tabulacji. Zauważ, że nazwałem tabelę źródłową "mytable" i użyłem wspólnych wyrażeń tabel dla czytelności, ale możesz również użyć podkwerend.

WITH unpivoted AS (
    SELECT id, value, question 
    FROM mytable a 
    UNPIVOT (value FOR question IN (quality,speed)) p 
) 
,counts AS (
    SELECT question, value, count(*) AS counts 
    FROM unpivoted 
    GROUP BY question, value 
) 
, repivoted AS (
    SELECT question, counts, [1], [2], [3] 
    FROM counts 
    PIVOT (count(value) FOR value IN ([1],[2],[3])) p 
) 
SELECT question, sum(counts*[1]) AS [1], sum(counts*[2]) AS [2], sum(counts*[3]) AS [3] 
    ,sum(counts*[1]) + 2*sum(counts*[2]) + 3*sum(counts*[3]) AS Total 
FROM repivoted 
GROUP BY question 

Uwaga, jeśli nie chcą podziału zapytanie jest prostsze:

WITH unpivoted AS (
    SELECT id, value, question 
    FROM mytable a 
    UNPIVOT (value FOR question IN (quality,speed)) p 
) 
, totals AS (
    SELECT question, value, count(value)*value AS score 
    FROM unpivoted 
    GROUP BY question, value 
) 
SELECT question, sum(score) AS score 
FROM totals 
GROUP BY question 
Powiązane problemy