2016-04-12 34 views
1

Boolean sütunları içeren bir tablom var. Bu sütunları, her birinin sahip olduğu gerçek değerler sayısına göre sıralamak istiyorum. Sütun değerleri sütununa göre sıralı.

kullanıyorum bir sütunda gerçek değerlerin sayısını saymak için bir yol bulmuş:

SELECT count(CASE WHEN col1 THEN 1 ELSE null END) as col1, 
     count(CASE WHEN col2 THEN 1 ELSE null END) as col2 
     .... 
FROM my_table; 

ancak bu yaklaşım iki sorun vardır: El ile sütun adlarını yazmak zorunda

  1. sonra değerin

tarafından sonucunu ve düzeni devrik zorunda

  • orada aw mı tüm işlem bir sorgu yapmak için ay? Doğru anladıysam,

  • +0

    Muhtemelen 'crosstab' onu ele alacaktır. Lütfen http://sqlfiddle.com örnek verilerini sağlayın ve istenen resultset – lad2025

    +0

    @ lad2025 'crosstab' ile de sütunların isimlerini elle yazmak zorundasınız. Temel olarak, OP'nin sunumuyla (sonuç açısından) işleyiş ile aynı olan bir dinamik ifade kullanmıyorsanız –

    +1

    Sorunuzu düzenleyin ve istediğiniz resulleri sağlayın –

    cevap

    0

    , dev bir union all ile yapabilirsiniz: Hâlâ sonuçları yazmanıza gerek rağmen

    select c.* 
    from ((select 'col1' as which, sum(case when col1 then 1 else 0 end) as cnt from t 
        ) union all 
         (select 'col2' as which, sum(case when col2 then 1 else 0 end) as cnt from t 
        ) union all 
         . . . 
        ) c 
    order by cnt desc; 
    

    , bu transpozisyonlar kaçınmak gelmez.

    1

    Bu aslında bir çapraz iş (veya diğer RDBMS'de "pivot") değil, tersi işlem ise, bir karşı-çaprazlama yaparsanız. Bir zarif teknik, LATERAL birleşiminde bir VALUES ifadesidir.

    temel sorgu ilgilenir ki, bu şöyle olabilir:

      Sonra değerin
    tarafından sonucunu ve düzeni devrik zorunda
  • SELECT c.col, c.ct 
    FROM (
        SELECT count(col1 OR NULL) AS col1 
         , count(col2 OR NULL) AS col2 
          -- etc. 
        FROM tbl 
        ) t 
        , LATERAL (
        VALUES ('col1', col1) 
         , ('col2', col2) 
          -- etc. 
        ) c(col, ct) 
    ORDER BY 2 
    

    Bu basit kısımdı. Öteki isteği zordur:

    1. el sütunları

    Bu fonksiyon, tablo adını alır ve sistem katalog pg_attribute meta verileri alır adlarını yazmak zorunda.

    CREATE OR REPLACE FUNCTION f_true_ct(_tbl regclass) 
        RETURNS TABLE (col text, ct bigint) AS 
    $func$ 
    BEGIN 
        RETURN QUERY EXECUTE (
        SELECT format(' 
         SELECT c.col, c.ct 
         FROM (SELECT %s FROM tbl) t 
          , LATERAL (VALUES %s) c(col, ct) 
         ORDER BY 2 DESC' 
        , string_agg (format('count(%1$I OR NULL) AS %1$I', attname), ', ') 
        , string_agg (format('(%1$L, %1$I)', attname), ', ') 
        ) 
        FROM pg_attribute 
        WHERE attrelid = _tbl    -- valid, visible, legal table name 
        AND attnum >= 1     -- exclude tableoid & friends 
        AND NOT attisdropped   -- exclude dropped columns 
        AND atttypid = 'bool'::regtype -- only character types 
        ); 
    END 
    $func$ LANGUAGE plpgsql; 
    

    Çağrı:

    SELECT * FROM f_true_ct('tbl'); -- table name optionally schema-qualified 
    

    Sonuç:

    col | ct 
    ------+--- 
    col1 | 3 
    col3 | 2 
    col2 | 1 
    

    İşleri tüm sıralamak için herhangi tablo için SQL enjeksiyonu karşı güvenli yukarıdaki sorgu dinamik uygulanması, var boolean sütunlarına göre true değerleri.

    fonksiyon parametresini anlamak için, bu okuyun:

    İlgili cevaplar daha açıklama ile:

  • +0

    'LATERAL ve VALUES' :) İnsanların neden SELECT * davranışını simüle etmek istediklerini merak ediyorum. – lad2025

    İlgili konular