Oracle SQL - 获取具有 NULL 或最大值的行
Oracle SQL - get the row with either NULL or the max value
我想要一个 return 总是一行的 where 子句。
如果对于 return 多行的查询,特定(可为空的 DateTime)字段中的值之一为 NULL,则它应该 return 此行。
如果没有值为 NULL 的行,它应该 return 具有最大日期时间的行。
例如:
Id
Date
1
2022-01-01
2
NULL
3
2021-01-01
在此示例中,ID=2 的行应 returned。
Id
Date
1
2022-01-01
2
2020-01-01
3
2021-01-01
在没有 NULL 行的示例中,ID=1 行应该 returned(因为它具有最高日期)。
这怎么可能?
提前致谢
我们可以在这里使用 ROW_NUMBER
和 two-tier 排序逻辑:
WITH cte AS (
SELECT t.*, ROW_NUMBER() OVER (
ORDER BY CASE WHEN Date IS NULL THEN 0 ELSE 1 END,
Date DESC) rn
FROM yourTable t
)
SELECT Id, Date
FROM cte
WHERE rn = 1;
第一个排序级别将 NULL
日期记录放在非 NULL
日期记录之前。第二种排序级别,在没有 NULL
日期记录的情况下使用,首先对较晚的日期进行排序。
如果您有 Oracle 12c 或更高版本:
Select *
From yourtable
Order by coalesce(date, to_date('9999-12-31', 'yyyy-mm-dd')) desc
Fetch first 1 rows only
感谢@littlefoot 和@tim_biegeleisen 指出 TOP n
语法在 Oracle 中不可用;我了解了 FETCH FIRST...!
我将这两个选项都放入示例数据中;它们在 VAR
列的值上有所不同。
SQL> with test (var, id, datum) as
2 (select 'A', 1, date '2022-01-01' from dual union all
3 select 'A', 2, NULL from dual union all
4 select 'A', 3, date '2021-01-01' from dual union all
5 --
6 select 'B', 1, date '2022-01-01' from dual union all
7 select 'B', 2, date '2020-01-01' from dual union all
8 select 'B', 3, date '2021-01-01' from dual
9 ),
CTE排名行;它们按 VAR
分区并按 datum
列的值排序,按降序排序,NULL
值在前:
10 temp as
11 (select var, id, datum,
12 rank() over (partition by var order by datum desc nulls first) rnk
13 from test
14 )
最终查询仅 returns 排名最高的行:
15 select var, id, datum
16 from temp
17 where rnk = 1;
V ID DATUM
- ---------- ----------
A 2
B 1 01.01.2022
SQL>
很快:
with temp as
(select var, id, datum,
rank() over (partition by var order by datum desc nulls first) rnk
from test
)
select var, id, datum
from temp
where rnk = 1;
您需要最高日期的 ID,其中 null 被认为高于任何实际日期。如果出现平局,您需要最小 ID。您可以为此使用 Oracle 的 KEEP LAST
:
select min(id) keep (dense_rank last order by date nulls last) from mytable;
我想要一个 return 总是一行的 where 子句。
如果对于 return 多行的查询,特定(可为空的 DateTime)字段中的值之一为 NULL,则它应该 return 此行。
如果没有值为 NULL 的行,它应该 return 具有最大日期时间的行。
例如:
Id | Date |
---|---|
1 | 2022-01-01 |
2 | NULL |
3 | 2021-01-01 |
在此示例中,ID=2 的行应 returned。
Id | Date |
---|---|
1 | 2022-01-01 |
2 | 2020-01-01 |
3 | 2021-01-01 |
在没有 NULL 行的示例中,ID=1 行应该 returned(因为它具有最高日期)。
这怎么可能?
提前致谢
我们可以在这里使用 ROW_NUMBER
和 two-tier 排序逻辑:
WITH cte AS (
SELECT t.*, ROW_NUMBER() OVER (
ORDER BY CASE WHEN Date IS NULL THEN 0 ELSE 1 END,
Date DESC) rn
FROM yourTable t
)
SELECT Id, Date
FROM cte
WHERE rn = 1;
第一个排序级别将 NULL
日期记录放在非 NULL
日期记录之前。第二种排序级别,在没有 NULL
日期记录的情况下使用,首先对较晚的日期进行排序。
如果您有 Oracle 12c 或更高版本:
Select *
From yourtable
Order by coalesce(date, to_date('9999-12-31', 'yyyy-mm-dd')) desc
Fetch first 1 rows only
感谢@littlefoot 和@tim_biegeleisen 指出 TOP n
语法在 Oracle 中不可用;我了解了 FETCH FIRST...!
我将这两个选项都放入示例数据中;它们在 VAR
列的值上有所不同。
SQL> with test (var, id, datum) as
2 (select 'A', 1, date '2022-01-01' from dual union all
3 select 'A', 2, NULL from dual union all
4 select 'A', 3, date '2021-01-01' from dual union all
5 --
6 select 'B', 1, date '2022-01-01' from dual union all
7 select 'B', 2, date '2020-01-01' from dual union all
8 select 'B', 3, date '2021-01-01' from dual
9 ),
CTE排名行;它们按 VAR
分区并按 datum
列的值排序,按降序排序,NULL
值在前:
10 temp as
11 (select var, id, datum,
12 rank() over (partition by var order by datum desc nulls first) rnk
13 from test
14 )
最终查询仅 returns 排名最高的行:
15 select var, id, datum
16 from temp
17 where rnk = 1;
V ID DATUM
- ---------- ----------
A 2
B 1 01.01.2022
SQL>
很快:
with temp as
(select var, id, datum,
rank() over (partition by var order by datum desc nulls first) rnk
from test
)
select var, id, datum
from temp
where rnk = 1;
您需要最高日期的 ID,其中 null 被认为高于任何实际日期。如果出现平局,您需要最小 ID。您可以为此使用 Oracle 的 KEEP LAST
:
select min(id) keep (dense_rank last order by date nulls last) from mytable;