2013-02-26 14 views
5

zakładając, że mam db, które posiadają poziomą strukturę takiego:jak liczyć wartości poziome w bazie danych?

ID | NAME | DATA1 | DATA2 | DATA3 | DATA4 | DATA5 | DATA6 | DATA7 
1 | mmm | 0 | 1 | 0 | 3 | 5 | 1 | 0 
2 | bbb | 0 | 0 | 0 | 1 | 0 | 1 | 1 

te informacje są pola danych i chciałbym policzyć wszystkie czasy, że pewien wyróżnik, takie jak „to coś więcej niż 0 "

drogą myślałem, że to jest pętla trought wszystkie pola i policzyć, czy COUNT() każde pole DATA, więc SUM() te 7 zapytań ... ktoś ma inny pomysł?

w tym przypadku wynik, więc "count every DATA field with a value over 0" byłby = 7

+2

Czy trzeba to zrobić dynamicznie lub kolumny są stałe? –

+0

cóż, pozwala zakładać, że kolumna jest stała, więc coulmn są od DATA1 do DATA7 w rzeczywistości dynamiczne rozwiązanie powinno być miłe. –

+1

najpierw znormalizuj swoje dane – Strawberry

Odpowiedz

5

Nie ma wbudowanej składni, które pozwalają zapoznać się z zestawu kolumn dynamicznie, to znaczy bez wyraźnego ich nazywania. Jeśli chcesz dynamiczność, musisz zapytać metadane, aby pobrać wymagane nazwy kolumn, a następnie dynamicznie utworzyć ostateczne zapytanie.

Przedtem jednak trzeba by mieć pojęcie, jak dokładnie powinno zostać wykonane zapytanie dynamiczne dotyczące samego zadania. Najpierw musisz rozwiązać ten problem na zbiorze kolumn skończonych.

Istnieje więcej niż jeden sposób rozwiązania tego problemu. Model method suggested by @bluefeet jest prawdopodobnie jednym z bardziej przejrzystych i mniej wydajnych. Można spróbować przynajmniej dwie alternatywy:

  1. hrabiego każdą kolumnę osobno za pomocą agregacji warunkowego i dodać do wszystkich wyników w jednym wyrażeniu: (. Na OR NULL Sztuką jest wyjaśnione here)

    SELECT 
        COUNT(DATA1 > 0 OR NULL) + 
        COUNT(DATA2 > 0 OR NULL) + 
        COUNT(DATA3 > 0 OR NULL) + 
        COUNT(DATA4 > 0 OR NULL) + 
        COUNT(DATA5 > 0 OR NULL) + 
        COUNT(DATA6 > 0 OR NULL) + 
        COUNT(DATA7 > 0 OR NULL) AS TOTAL 
    FROM yourtable 
    ; 
    

  2. Odłącz kolumny DATA, używając łączenia krzyżowego do wirtualnej tabeli, a następnie zastosuj warunek do kolumny niepodzielonej:

    SELECT 
        COUNT(*) AS TOTAL 
    FROM (
        SELECT 
        CASE s.col 
         WHEN 'DATA1' THEN DATA1 
         WHEN 'DATA2' THEN DATA2 
         WHEN 'DATA3' THEN DATA3 
         WHEN 'DATA4' THEN DATA4 
         WHEN 'DATA5' THEN DATA5 
         WHEN 'DATA6' THEN DATA6 
         WHEN 'DATA7' THEN DATA7 
        END AS DATA 
        FROM yourtable 
        CROSS JOIN (
        SELECT 'DATA1' AS col 
        UNION ALL SELECT 'DATA2' 
        UNION ALL SELECT 'DATA3' 
        UNION ALL SELECT 'DATA4' 
        UNION ALL SELECT 'DATA5' 
        UNION ALL SELECT 'DATA6' 
        UNION ALL SELECT 'DATA7' 
    ) s 
    ) s 
    WHERE DATA > 0 
    ; 
    

    (W pewnym sensie jest to podobne do użytkownika @ bluefeet sugestii, to po prostu nie zatrudnia żadnych związków zawodowych.)

+0

bardzo elegancki i dobrze wyjaśniony, wielkie dzięki, sztuczka OR NULL jest naprawdę fajna! –

3

Ponieważ dane te nie są znormalizowane należy UNPIVOT dane, aby uzyskać wynik. MySQL nie ma funkcji unpivot, więc możesz użyć zapytania UNION ALL do konwersji kolumn w wiersze. Gdy dane znajdują się w wierszach, możesz z łatwością policzyć liczbę wartości. Chciałbym użyć coś podobnego do tego:

select count(*) total 
from 
(
    select id, name, 'data1' col, data1 as value 
    from yourtable 
    union all 
    select id, name, 'data2' col, data2 as value 
    from yourtable 
    union all 
    select id, name, 'data3' col, data3 as value 
    from yourtable 
    union all 
    select id, name, 'data4' col, data4 as value 
    from yourtable 
    union all 
    select id, name, 'data5' col, data5 as value 
    from yourtable 
    union all 
    select id, name, 'data6' col, data6 as value 
    from yourtable 
    union all 
    select id, name, 'data7' col, data7 as value 
    from yourtable 
) src 
where value > 0 

Zobacz SQL Fiddle with Demo

+0

związek wszystko - co z osiągami? – VAV

+0

@ VAV 'UNION ALL' działa lepiej niż' UNION', ponieważ nie usuwa żadnych duplikatów. – Taryn

+1

tak, i nie dokonuj żadnego "sortowania", ale moje pytanie o siedmiokrotne "unii" i agregowanie wynikowego zbioru danych dla dużych tabel - czy to jest rozwiązanie produkcyjne? – VAV

Powiązane problemy