PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

PostgreSQL 9.3:Динамична въртяща се таблица

Можете да направите това с crosstab() от допълнителния модул tablefunc:

SELECT b
     , COALESCE(a1, 0) AS "A1"
     , COALESCE(a2, 0) AS "A2"
     , COALESCE(a3, 0) AS "A3"
     , ... -- all the way up to "A30"
FROM   crosstab(
         'SELECT colb, cola, 1 AS val FROM matrix
          ORDER  BY 1,2'
        , $$SELECT 'A'::text || g FROM generate_series(1,30) g$$
       ) AS t (b text
             , a1  int, a2  int, a3  int, a4  int, a5  int, a6  int
             , a7  int, a8  int, a9  int, a10 int, a11 int, a12 int
             , a13 int, a14 int, a15 int, a16 int, a17 int, a18 int
             , a19 int, a20 int, a21 int, a22 int, a23 int, a24 int
             , a25 int, a26 int, a27 int, a28 int, a29 int, a30 int);

Ако NULL вместо 0 работи също, може да бъде просто SELECT * във външната заявка.
Подробно обяснение:

  • PostgreSQL Crosstab Query

Специалната "трудност" тук:няма действителна "стойност". Така че добавете 1 AS val като последна колона.

Неизвестен брой категории

Напълно динамична заявка (с неизвестен тип резултат) не е възможна в една заявка. Нуждаете се от два запитвания. Първо изградете динамично изявление като горното, след което го изпълнете. Подробности:

  • Избиране на множество max() стойности с помощта на един SQL израз

  • PostgreSQL конвертира колони в редове? Транспониране?

  • Динамично генериране на колони за кръстосана таблица в PostgreSQL

  • Динамична алтернатива на завъртане с CASE и GROUP BY

Твърде много категории

Ако надвишите максималния брой колони (1600), класическата кръстосана таблица е невъзможна, тъй като резултатът не може да бъде представен с отделни колони. (Освен това човешките очи едва ли биха могли да разчетат таблица с толкова много колони)

Масиви или типове документи като hstore или jsonb са алтернативата. Ето решение с масиви:

SELECT colb, array_agg(cola) AS colas
FROM  (
   SELECT colb, right(colb, -1)::int AS sortb
        , CASE WHEN m.cola IS NULL THEN 0 ELSE 1 END AS cola
   FROM        (SELECT DISTINCT colb FROM matrix) b
   CROSS  JOIN (SELECT DISTINCT cola FROM matrix) a
   LEFT   JOIN matrix m USING (colb, cola)
   ORDER  BY sortb, right(cola, -1)::int 
   ) sub
GROUP  BY 1, sortb
ORDER  BY sortb;
  • Изградете пълната мрежа от стойности с:

                (SELECT DISTINCT colb FROM matrix) b
    CROSS  JOIN (SELECT DISTINCT cola FROM matrix) a
    
  • LEFT JOIN съществуващи комбинации, подредете по числовата част на името и обединете в масиви.

    • right(colb, -1)::int отрязва главния символ от „A3“ и прехвърля цифрите към цяло число, така че да получим правилен ред на сортиране.

Основна матрица

Ако просто искате таблица с 0 1 където x = y , това може да бъде по-евтино:

SELECT x, array_agg((x = y)::int) AS y_arr
FROM   generate_series(1,10) x
     , generate_series(1,10) y
GROUP  BY 1
ORDER  BY 1;

SQL Fiddle надграждане на този, който сте предоставили в коментарите.

Имайте предвид, че sqlfiddle.com в момента има грешка, която убива показването на стойности на масива. Затова прехвърлям към text там, за да го заобиколите.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Внедряване на настройка с множество центрове за данни за PostgreSQL – част първа

  2. Автоматично тестване на процеса на надстройка за PostgreSQL

  3. как да емулирам вмъкване игнориране и при актуализиране на дублиран ключ (sql обединяване) с postgresql?

  4. Импортиране на .sql файл на windows в postgresql

  5. Как да разположите PostgreSQL за висока наличност