Этот первый запрос следует шаблону ответа на дублирующий вопрос , включенного здесь для сравнения.
WITH numbered AS (
SELECT row_number() OVER
(PARTITION BY ID ORDER BY COD, DIAG)
AS seq,
t.*
FROM SO58566470 t)
SELECT ID,
max(CASE WHEN seq = 1 THEN COD END) AS COD1,
max(CASE WHEN seq = 1 THEN DIAG END) AS DIAG1,
max(CASE WHEN seq = 2 THEN COD END) AS COD1,
max(CASE WHEN seq = 2 THEN DIAG END) AS DIAG1,
max(CASE WHEN seq = 3 THEN COD END) AS COD3,
max(CASE WHEN seq = 3 THEN DIAG END) AS DIAG3
FROM numbered n
GROUP BY ID;
Но это действительно наивное использование оконных функций, поскольку ономог бы увеличить окно, рассчитав другие значения в то же время. Первый запрос уже собирает и пересекает разделенные строки, чтобы получить номер строки, однако он по сути повторяет этот процесс дважды, собирая значения в следующем запросе с использованием агрегатных функций max ().
Следующий запрос выглядит длиннее ивозможно, более сложный, но он использует преимущества секционированных данных (то есть данных окна), собирая преобразованные значения в одном и том же процессе. Но поскольку оконные функции обязательно работают с каждой строкой, возникает необходимость отфильтровывать «неполные» строки. Я не проводил никакого профилирования по запросам, но подозреваю, что этот второй запрос в целом гораздо эффективнее.
WITH transform AS (
SELECT id,
lag(COD, 0) OVER IDWin AS COD1,
lag(DIAG, 0) OVER IDWin AS DIAG1,
lag(COD, 1) OVER IDWin AS COD2,
lag(DIAG, 1) OVER IDWin AS DIAG2,
lag(COD, 2) OVER IDWin AS COD3,
lag(DIAG, 2) OVER IDWin AS DIAG3,
row_number() OVER IDWin AS seq
FROM SO58566470 t
WINDOW IDWin AS (PARTITION BY ID ORDER BY COD, DIAG)
ORDER BY ID, SEQ
),
last AS (
SELECT id, max(seq) as maxseq
FROM transform
GROUP BY id
)
SELECT transform.*
FROM transform
JOIN last
ON transform.id = last.id AND transform.seq = last.maxseq
ORDER BY id;