给定一个包含 4 列或更多列的“摘要”表:
(ID1, ID2, SortOrder, BooleanYN)
对于
ID1
的每个值,我想要与具有最高 ID2
值的 BooleanYN = Y
行相对应的 SortOrder
值(如果存在此类记录)。
示例:
ID1 | ID2 | 排序 | 布尔YN |
---|---|---|---|
1 | 10 | 1 | 是 |
1 | 20 | 2 | N |
1 | 30 | 3 | 是 |
1 | 40 | 4 | N |
我正在寻找
(1, 30)
,因为具有 SortOrder
的 ID1 = 1
的“最新”(基于 BooleanYN = 'Y'
)行是具有 ID2 = 30
的行。
我在这里用示例数据构建了一个 SQL Fiddle:
http://sqlfiddle.com/#!4/a5bc5/6
此查询在 Fiddle 中不起作用,因为 Oracle 11g 不支持
OUTER APPLY
,但它在 Oracle 19 中有效。
SELECT
p.person_id,
mmr.appointment_id,
flu.appointment_id,
covid.appointment_id,
hiv.appointment_id
FROM
person p
OUTER APPLY (
SELECT vs.appointment_id
FROM vaccination_summary vs
WHERE vs.person_id = p.person_id
AND mmr_yn = 'Y'
ORDER BY vs.appointment_date DESC
FETCH FIRST ROW ONLY
) mmr
OUTER APPLY (
SELECT vs.appointment_id
FROM vaccination_summary vs
WHERE vs.person_id = p.person_id
AND flu_yn = 'Y'
ORDER BY vs.appointment_date DESC
FETCH FIRST ROW ONLY
) flu
OUTER APPLY (
SELECT vs.appointment_id
FROM vaccination_summary vs
WHERE vs.person_id = p.person_id
AND covid_yn = 'Y'
ORDER BY vs.appointment_date DESC
FETCH FIRST ROW ONLY
) covid
OUTER APPLY (
SELECT vs.appointment_id
FROM vaccination_summary vs
WHERE vs.person_id = p.person_id
AND hiv_yn = 'Y'
ORDER BY vs.appointment_date DESC
FETCH FIRST ROW ONLY
) hiv;
看起来SUPER不优雅且效率低下。
当然必须有更好的方法来使用窗口函数来做到这一点......或者也许取消旋转然后重新旋转?
方法很多。一种是窗口化,它本身可以通过多种方式完成。这是一个:
SELECT *
FROM (SELECT x.*,
ROW_NUMBER() OVER (PARTITION BY id1 ORDER BY DECODE(BooleanYN,'Y',1,2),SortOrder DESC) seq
FROM tablename x)
WHERE seq = 1
一种没有子查询的旧预窗口方法:
SELECT id1,
SUBSTR(MAX(DECODE(BooleanYN ='Y',1,2)||TO_CHAR(LPAD(SortOrder,3,'0')||id2),4) id2
FROM tablename
GROUP BY id1
当然还有子查询方法:
SELECT id1,
id2
FROM tablename t1
WHERE sortorder = (SELECT MAX(sortorder)
FROM tablename t2
WHERE t2.id1 = t1.id1
AND t2.booleanyn = 'Y')
AND boooleanyn = 'Y'