Объединение 2 строк в один в Postgresql - PullRequest
1 голос
/ 15 апреля 2020

У меня есть эта таблица:

CREATE TABLE mytable
(
id integer NOT NULL,
  rank integer,
  col1 text,
  col2 text,
  CONSTRAINT mytable_pk PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);


INSERT INTO mytable(id, rank, col1, col2)  VALUES (1, 1, 'c', 'c');
INSERT INTO mytable(id, rank, col1, col2)  VALUES (2, 2, 'a', 'a');
INSERT INTO mytable(id, rank, col1, col2)  VALUES (3, 2, 'b', NULL);
INSERT INTO mytable(id, rank, col1, col2)  VALUES (4, 3, 'c', 'c');

Мне нужно сделать запрос в postgresql 9.0, который "объединит" две строки с одинаковым значением "rank" в одну строку, с этим правилом: for col1 и col2, выберите значения с более высоким значением "id", но когда это значение равно NULL, выберите другое значение (примечание: строки с одинаковым значением "rank" не могут быть больше 2)

ожидаемый результат:

rank    col1     col2
------------------------------
1   c   c
2   b   a
3   c   c

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

Попробуйте:

select mt.rank,
       (select col1 from mytable where id = max(case when mt.col1 is not null then mt.id end)) as col1,
       (select col2 from mytable where id =max(case when mt.col2 is not null then mt.id end)) as col2
from mytable mt
group by mt.rank 
order by mt.rank; 

Другой способ, используя with и self join

with tab as (select rank, 
             max(case when col1 is not null then id end) col1,
             max(case when col2 is not null then id end) col2 from mytable
            group by rank)

select tab.rank "rank", mt1.col1 "col1", mt2.col2 "col2" 
from tab
left join mytable mt1 on mt1.id=tab.col1 
left join mytable mt2 on mt2.id=tab.col2 
order by tab.rank 
0 голосов
/ 15 апреля 2020

Кстати: rank - это ключевое слово, я должен был переименовать в rnk


SELECT a.rnk
        , COALESCE(a.col1,b.col1) AS col1
        , COALESCE(a.col2,b.col1) AS col2
FROM mytable a
LEFT JOIN mytable b ON a.rnk = b.rnk AND a.id > b.id
WHERE NOT EXISTS (
        SELECT * FROM mytable x
        WHERE x.rnk = a.rnk
        AND x.id > a.id
        )
        ;

То же самое, используя функции WINDOW:


SELECT rnk
        ,COALESCE(col1,lead1) AS col1
        ,COALESCE(col2,lead2) AS col2
FROM (
        SELECT rnk,col1,col2
        , rank() OVER (www) AS zrank    -- REVERSED order (per rnk)
        , LEAD(col1) OVER www AS lead1  -- Value for next record , if any
        , LEAD(col2) OVER www AS lead2  -- Value for next record , if any

        FROM mytable
                WINDOW www AS (partition BY rnk ORDER BY id DESC)
        ) xxx
WHERE zrank = 1
        ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...