我在 Oracle 18c 中有一个 RoadInsp 表。为了解决这个问题,我已将数据放入 CTE 中:
with roadinsp (objectid, asset_id, date_) as (
select 1, 1, to_date('2016-04-01','YYYY-MM-DD') from dual union all
select 2, 1, to_date('2019-03-01','YYYY-MM-DD') from dual union all
select 3, 1, to_date('2022-01-01','YYYY-MM-DD') from dual union all
select 4, 2, to_date('2016-04-01','YYYY-MM-DD') from dual union all
select 5, 2, to_date('2021-01-01','YYYY-MM-DD') from dual union all
select 6, 3, to_date('2022-03-01','YYYY-MM-DD') from dual union all
select 7, 3, to_date('2016-04-01','YYYY-MM-DD') from dual union all
select 8, 3, to_date('2018-03-01','YYYY-MM-DD') from dual union all
select 9, 3, to_date('2013-03-01','YYYY-MM-DD') from dual union all
select 10, 3, to_date('2010-06-01','YYYY-MM-DD') from dual
)
select * from roadinsp
OBJECTID ASSET_ID DATE_
---------- ---------- ----------
1 1 2016-04-01
2 1 2019-03-01
3 1 2022-01-01 --select this row
4 2 2016-04-01
5 2 2021-01-01 --select this row
6 3 2022-03-01 --select this row
7 3 2016-04-01
8 3 2018-03-01
9 3 2013-03-01
10 3 2010-06-01
我使用的 GIS 软件只允许我在 WHERE 子句/SQL 表达式中使用 SQL,而不是完整的 SELECT 查询。
我想使用 WHERE 子句选择每组中最大的 1 个。换句话说,对于每个 ASSET_ID,我想选择具有最新日期的行。
作为一个实验,我想专门使用 EXISTS 运算符进行选择。
原因是:虽然这篇文章在技术上涉及 Oracle(因为这是 S.O. 社区成员可以访问的内容),但实际上,我想使用名为“文件地理数据库”的专有数据库中的逻辑。文件地理数据库的 SQL 支持非常有限; SQL-92 语法的一个小子集。但它似乎确实支持 EXISTS 和子查询,尽管不支持相关子查询。 非常沮丧。
ArcGIS 中使用的查询表达式的 SQL 参考
带有比较运算符的标量子查询。标量子查询返回单个值,例如:
- EXISTS 谓词,例如:
GDP2006 > (SELECT MAX(GDP2005) FROM countries)
对于文件地理数据库,集合函数 AVG、COUNT、MIN、MAX 和 SUM 只能用于标量子查询。
EXISTS (SELECT * FROM indep_countries WHERE COUNTRY_NAME = 'Mexico')
使用 EXISTS 运算符,有没有办法选择每组中最大的 1 个? (请记住上述限制)
编辑:如果资产有多行具有相同的顶级日期,则应仅选择其中一行(任意)。
rank
分析函数可以完成这项工作,如果您可以使用的话(Oracle 18c 当然支持它)。
样本数据:SQL> with roadinsp (objectid, asset_id, date_) as (
2 select 1, 1, to_date('2016-04-01','YYYY-MM-DD') from dual union all
3 select 2, 1, to_date('2019-03-01','YYYY-MM-DD') from dual union all
4 select 3, 1, to_date('2022-01-01','YYYY-MM-DD') from dual union all
5 select 4, 2, to_date('2016-04-01','YYYY-MM-DD') from dual union all
6 select 5, 2, to_date('2021-01-01','YYYY-MM-DD') from dual union all
7 select 6, 3, to_date('2022-03-01','YYYY-MM-DD') from dual union all
8 select 7, 3, to_date('2016-04-01','YYYY-MM-DD') from dual union all
9 select 8, 3, to_date('2018-03-01','YYYY-MM-DD') from dual union all
10 select 9, 3, to_date('2013-03-01','YYYY-MM-DD') from dual union all
11 select 10, 3, to_date('2010-06-01','YYYY-MM-DD') from dual
12 ),
查询从这里开始:首先按日期降序排列每个
asset_id
的行:
13 temp as
14 (select r.*,
15 rank() over (partition by asset_id order by date_ desc) rnk
16 from roadinsp r
17 )
最后,获取排名最高的行:
18 select *
19 from temp
20 where rnk = 1;
OBJECTID ASSET_ID DATE_ RNK
---------- ---------- ---------- ----------
3 1 2022-01-01 1
5 2 2021-01-01 1
6 3 2022-03-01 1
SQL>
<snip>
13 select r.objectid, r.asset_id, r.date_
14 from roadinsp r
15 where (r.asset_id, r.date_) in (select t.asset_id, t.max_date
16 from (select a.asset_id, max(a.date_) max_date
17 from roadinsp a
18 group by a.asset_id
19 ) t
20 );
OBJECTID ASSET_ID DATE_
---------- ---------- ----------
6 3 2022-03-01
5 2 2021-01-01
3 1 2022-01-01
SQL>