【问题标题】:Recursive sql query for folding rows into each other用于将行相互折叠的递归 sql 查询
【发布时间】:2021-05-03 14:20:56
【问题描述】:

我已经为这个问题苦苦挣扎了很长一段时间,但我相信有办法解决这个问题。我有一张桌子,上面有我们设施的住宿记录。每行都有一个clientID、rowID、一个开始日期、一个结束日期、一个类型和上次停留的rowID。

类似这样的:

Client id stayId previous_stay start_date end_date type
1 101 null 1-1-2010 20-6-2010 A
1 105 101 1-7-2010 30-12-2020 B
1 108. null 8-10-2012 10-12-2012 B

我想写一个查询来为我们拥有的每个客户得到这样的结果

Client id stayId first_stay start_date end_date types
1 105 101 1-1-2010 30-12-2010 2
1 108 null 8-10-2012 10-12-2012 1

我认为最好的方法是递归 sql 查询,但我真的不知道该怎么做,谁能帮助我? 我正在使用 oracle sql

【问题讨论】:

  • 2010 是否在所需输出的 ​​end_date 中有错字?除此之外-这里的“递归”或“分层”是什么?无需进一步解释,您似乎只需要一个简单的聚合 - 正如 Gordon Linoff 在他的回答中已经证明的那样。
  • 我将问题编辑得更准确,我需要对上一个逗留列进行递归
  • 编辑后的输出没有意义。对于stayid = 108,为什么first_stay为空?该序列中的第一次停留是 108,而不是空值(至少,根据您显示的第一对停留的“首次停留”来判断)。此外,您在 2020 年的输入和 2010 年的输出之间仍然存在差异。您的意思是输入中的 2010,end_date,第二行?

标签: sql oracle recursion rows


【解决方案1】:

你只是想要聚合吗?

select clientid, max(stayid), min(stayid), min(startdate), max(enddate),
       count(distinct type)
from t
group by clientid;

【讨论】:

  • 不,也许我应该解释得更好一点,但是客户可以有多个不同的住宿,彼此不跟随
  • 我将问题更新为更准确
【解决方案2】:

如果我正确理解您的任务,这可以通过 connect by 查询(分层查询)然后聚合来完成,这可以在同一个 select 语句中完成。像这样:

alter session set nls_date_format = 'dd-mm-yyyy';
with
  sample_data (clientid, stayid, previous_stay, start_date, end_date, type_) as (
    select 1, 101, null, to_date('1-1-2010') , to_date('20-6-2010') , 'A' from dual
    union all
    select 1, 105, 101 , to_date('1-7-2010') , to_date('30-12-2020'), 'B' from dual
    union all
    select 1, 108, null, to_date('8-10-2012'), to_date('10-12-2012'), 'B' from dual
  )
select  clientid, 
        min(case connect_by_isleaf when 1 then stayid end) as stayid,
        min(case level             when 1 then stayid end) as first_stay,
        min(start_date) as first_start_date,
        max(end_date)   as last_end_date,
        count(distinct type_) as distinct_types
from    sample_data
start   with previous_stay is null
connect by prior stayid = previous_stay and prior clientid = clientid
group   by clientid, connect_by_root(stayid)
;

CLIENTID STAYID FIRST_STAY FIRST_START_DATE LAST_END_DATE DISTINCT_TYPES
-------- ------ ---------- ----------       ------------- --------------
       1    105        101 01-01-2010       30-12-2020                 2
       1    108        108 08-10-2012       10-12-2012                 1

输出在两个地方与您的不同:STAYID 105 的最后结束日期是 2020 年,而不是您显示的 2010 年,因为输入显示 2020。(可能是您的示例输入或示例中的错字输出)。而且,对于 STAYID 108,第一个stayid 是 108,而不是您在输出中显示的 NULL;实际上,NULL 不是输入中任何停留的 STAYID,因此在输出中显示为“第一次停留”是没有意义的。

【讨论】:

  • 这行得通!太棒了,谢谢你的帮助!
猜你喜欢
  • 2014-06-11
  • 2020-03-27
  • 1970-01-01
  • 2020-04-02
  • 2023-03-22
  • 1970-01-01
  • 2016-11-19
  • 2017-12-27
  • 1970-01-01
相关资源
最近更新 更多