将行相互折叠的递归 sql 查询

Recursive sql query for folding rows into each other

我已经为这个问题苦苦挣扎了一段时间,但我相信有办法解决。我有一个 table,里面有我们设施的住宿记录。每行都有一个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 查询,但我真的不知道该怎么做,有人可以帮助我吗? 我正在使用甲骨文 sql

你只是想要聚合吗?

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

如果我对您的任务理解正确,这可以通过 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,因此在输出中显示为“首次住宿”没有任何意义。