将行相互折叠的递归 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,因此在输出中显示为“首次住宿”没有任何意义。
我已经为这个问题苦苦挣扎了一段时间,但我相信有办法解决。我有一个 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,因此在输出中显示为“首次住宿”没有任何意义。