使用 EXISTS 选择每组中最大的 1 个

问题描述 投票:0回答:1

我在 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 参考

文件地理数据库中的子查询支持仅限于以下内容:

    带有比较运算符的标量子查询。标量子查询返回单个值,例如:
  • GDP2006 > (SELECT MAX(GDP2005) FROM countries)

    对于文件地理数据库,集合函数 AVG、COUNT、MIN、MAX 和
    SUM 只能用于标量子查询。

  • EXISTS 谓词,例如:
  • EXISTS (SELECT * FROM indep_countries WHERE COUNTRY_NAME = 'Mexico')

    
    


问题:

使用 EXISTS 运算符,有没有办法选择每组中最大的 1 个? (请记住上述限制)

编辑:

如果资产有多行具有相同的顶级日期,则应仅选择其中一行(任意)。

sql oracle greatest-n-per-group arcgis exists
1个回答
0
投票
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>

© www.soinside.com 2019 - 2024. All rights reserved.