2012-12-07 7 views
5

Mam tabelę z kolumnami N. Nazwijmy je: c1, c2, c3, c4, ... cN. Wśród wielu wierszy chcę uzyskać pojedynczy wiersz z COUNT DISTINCT(cX) dla każdego X w [1, N].Jak wykonać tę samą agregację w każdej kolumnie bez wyświetlania kolumn?

c1 | c2 | ... | cn 
0 | 4 | ... | 1 

Czy jest sposób, w jaki mogę to zrobić (w procedurze przechowywanej) bez ręcznego wpisywania każdej nazwy kolumny do zapytania?

Dlaczego?

Mieliśmy problem z tym, że błędy w serwerach aplikacji oznaczają, że przepisujemy dobre wartości kolumn z późniejszymi wstawionymi śmieciami. Aby rozwiązać ten problem, przechowuję strukturę logiczną informacji, gdzie każdy wiersz reprezentuje logiczną kwerendę UPDATE. Następnie, gdy otrzymam sygnał, że rekord jest kompletny, mogę określić, czy jakiekolwiek wartości zostały (błędnie) nadpisane.

Przykład pojedynczego poprawnego rekordu w wielu wierszach: w każdej kolumnie znajduje się co najwyżej jedna wartość.

| id | initialize_time | start_time | end_time | 
| 1 | 12:00am   | NULL  | NULL  | 
| 1 | 12:00am   | 1:00pm  | NULL  | 
| 1 | 12:00am   | NULL  | 2:00pm | 

Reconciled row: 
| 1 | 12:00am   | 1:00pm  | 2:00pm | 

Przykładem nieprzejednanej zapis, że chcę, aby wykryć:

| id | initialize_time | start_time | end_time | 
| 1 | 12:00am   | NULL  | NULL  | 
| 1 | 12:00am   | 1:00pm  | NULL  | 
| 1 | 9:00am   | 1:00pm  | 2:00pm | -- New initialize time => irreconcilable! 
+0

Czy pytasz, jak pobrać nazwy kolumn lub jak przeprowadzić agregację? –

+0

Wiem, jak pobrać nazwy kolumn, ale nie wiem, co zrobić, aby rozwinąć wyrażenie wokół każdej nazwy kolumny w zapytaniu. Chcę uniknąć 'SELECT COUNT DISTINCT (c1), COUNT DISTINCT (c2), ..., COUNT DISTINCT (cN) FROM ...' w mojej procedurze przechowywanej. –

+0

Możesz to zrobić z dynamicznym SQL, oczywiście. Przy okazji, jak duże jest X? – dezso

Odpowiedz

3

Trzeba dla dynamicznego SQL, co oznacza, że ​​trzeba stworzyć funkcję lub uruchomić polecenie DO. Ponieważ nie można zwracać wartości bezpośrednio od niego, funkcja plpgsql to:

CREATE OR REPLACE function f_count_all(_tbl text 
          , OUT columns text[], OUT counts bigint[]) 
    RETURNS record LANGUAGE plpgsql AS 
$func$ 
BEGIN 

EXECUTE (
    SELECT 'SELECT 
    ARRAY[' || string_agg('''' || quote_ident(attname) || '''', ', ') || '], 
    ARRAY[' || string_agg('count(' || quote_ident(attname) || ')', ', ') || '] 
    FROM ' || _tbl 
    FROM pg_attribute 
    WHERE attrelid = _tbl::regclass 
    AND attnum >= 1   -- exclude tableoid & friends (neg. attnum) 
    AND attisdropped is FALSE -- exclude deleted columns 
    GROUP BY attrelid 
    ) 
INTO columns, counts; 

END 
$func$; 

połączeń:

SELECT * FROM f_count_all('myschema.mytable'); 

Powroty:

columns  | counts 
--------------+-------- 
{c1, c2, c3,} | {17 1,0} 

więcej wyjaśnień i linki o dynamicznym SQL i EXECUTE w this related question - lub kilka więcej tutaj na SO, try this serach.

Bardzo podobny do tego pytania:
postgresql - count (no null values) of each column in a table

Można nawet spróbować i powrócić polimorficzny typ rekordu, aby uzyskać pojedyncze kolumny dynamicznie, ale to dość skomplikowane i zaawansowane. Prawdopodobnie za dużo wysiłku dla twojej sprawy. Więcej w this related answer.

Powiązane problemy