我有一个客户数据表,其选定列如下所示:
SELECT
bt.*,
dt.f1,
-- ...,
dt.fn
FROM
base_table AS bt
INNER JOIN object AS o ON o.id = bt.role
INNER JOIN Person AS dt ON dt.entity_id = bt.entity_id
WHERE
o.type='Person'
UNION ALL
SELECT
bt.*,
dt.f1,
-- ...,
dt.fn
FROM
base_table AS bt
INNER JOIN object AS o ON o.id = bt.role
INNER JOIN [Legal Person] AS dt ON dt.entity_id = bt.entity_id
WHERE
o.type='Legal Person'
UNION ALL
SELECT
bt.*,
dt.f1,
-- ...,
dt.fn
FROM
base_table AS bt
INNER JOIN object AS o ON o.id = bt.role
INNER JOIN Counterpart AS dt ON dt.entity_id = bt.entity_id
WHERE
o.type='Counterpart'
在通过Client_ID然后通过From_date按升序排列数据之后,我的目标是在每次将状态与前一行进行比较时,该客户端的状态发生变化时添加计算的Rank_ID。我想要的Rank_ID所需的值如下所示:
Row_ID Client_ID Status_ID From_date To_date
1 123456 4 20/12/2007 18:02 20/12/2007 18:07
2 789087 4 20/12/2007 18:02 20/12/2007 18:07
3 789087 4 20/12/2007 18:07 20/12/2007 18:50
4 789087 4 20/12/2007 18:50 21/12/2007 10:38
5 123456 4 20/12/2007 18:07 20/12/2007 18:50
6 123456 4 20/12/2007 18:50 21/12/2007 10:38
7 123456 4 21/12/2007 10:38 21/12/2007 16:39
8 789087 4 21/12/2007 10:38 21/12/2007 17:54
9 789087 4 21/12/2007 17:54 21/12/2007 18:32
10 789087 4 21/12/2007 18:32 22/12/2007 06:48
11 123456 5 21/12/2007 16:39
12 789087 5 22/12/2007 06:48 22/12/2007 10:53
13 789087 4 22/12/2007 10:53 22/12/2007 11:51
14 789087 5 22/12/2007 11:51
我正在尝试使用DENSE_RANK作为分析函数,我的“错误”SQL代码低于
Row_ID Client_ID Status_ID From_date To_date Rank_ID
1 123456 4 20/12/2007 18:02 20/12/2007 18:07 1
5 123456 4 20/12/2007 18:07 20/12/2007 18:50 1
6 123456 4 20/12/2007 18:50 21/12/2007 10:38 1
7 123456 4 21/12/2007 10:38 21/12/2007 16:39 1
11 123456 5 21/12/2007 16:39 2
2 789087 4 20/12/2007 18:02 20/12/2007 18:07 3
3 789087 4 20/12/2007 18:07 20/12/2007 18:50 3
4 789087 4 20/12/2007 18:50 21/12/2007 10:38 3
8 789087 4 21/12/2007 10:38 21/12/2007 17:54 3
9 789087 4 21/12/2007 17:54 21/12/2007 18:32 3
10 789087 4 21/12/2007 18:32 22/12/2007 06:48 3
12 789087 5 22/12/2007 06:48 22/12/2007 10:53 4
13 789087 4 22/12/2007 10:53 22/12/2007 11:51 5
14 789087 5 22/12/2007 11:51 6
然而,我遇到的问题是它给出了编写的SQL代码,它按如下方式计算Rank_ID:
SELECT t1.*, DENSE_RANK () OVER (ORDER BY t1.client_id, t1.status_id) rank_id
FROM (SELECT c.client_ID, c.status_id, c.from_date, c.to_date
FROM client c
ORDER BY c.client_id, c.from_date) t1
ORDER BY t1.client_id, t1.from_date
对于记录13,返回的Rank_ID为3(而我希望5表示该客户端的状态发生变化,与该客户端的前一记录的状态相比),对于记录14,返回的Rank_ID为4,而我想要6,因为与前一行相比,该客户的状态再次发生变化。
我想问题是我的SQL通过Client_ID然后按Status_ID对数据进行排序,因此我可以看出为什么它会产生它给出的答案。问题是无论我对DENSE_RANK行做了什么改变,我都无法得到我想要的答案。
任何帮助都将不胜感激。
答案 0 :(得分:1)
据我所知,这就是你所需要的:
select client_ID, status_id, from_date, to_date,
sum(start_of_group) over (order by client_ID, from_date) + 1 rank
from (SELECT c.client_ID, c.status_id, c.from_date, c.to_date,
case when lag(c.client_ID, 1, c.client_ID) over (order by c.client_ID, c.from_date) = c.client_ID
and lag(c.status_id, 1, c.status_id) over (order by c.client_ID, c.from_date) = c.status_id
then 0 else 1 end start_of_group
FROM client c)
order by client_ID, from_date
答案 1 :(得分:0)
问题在于,您需要根据状态的变化对排名进行分区,而不是状态的值。我在输出中留下了一些额外的列,以便您可以看到它是如何导出的:
WITH dat as (
SELECT 1 row_id, 123456 client_id, 4 status, to_date('20/12/2007 18:02','dd/mm/yyyy hh24:mi') frdate, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 2 row_id, 789087 client_id, 4 status, to_date('20/12/2007 18:02','dd/mm/yyyy hh24:mi') frdate, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 3 row_id, 789087 client_id, 4 status, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') frdate, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 4 row_id, 789087 client_id, 4 status, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') frdate, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 5 row_id, 123456 client_id, 4 status, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') frdate, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 6 row_id, 123456 client_id, 4 status, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') frdate, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 7 row_id, 123456 client_id, 4 status, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') frdate, to_date('21/12/2007 16:39','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 8 row_id, 789087 client_id, 4 status, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') frdate, to_date('21/12/2007 17:54','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 9 row_id, 789087 client_id, 4 status, to_date('21/12/2007 17:54','dd/mm/yyyy hh24:mi') frdate, to_date('21/12/2007 18:32','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 10 row_id, 789087 client_id, 4 status, to_date('21/12/2007 18:32','dd/mm/yyyy hh24:mi') frdate, to_date('22/12/2007 06:48','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 11 row_id, 123456 client_id, 5 status, to_date('21/12/2007 16:39','dd/mm/yyyy hh24:mi') frdate, null from dual union all
SELECT 12 row_id, 789087 client_id, 5 status, to_date('22/12/2007 06:48','dd/mm/yyyy hh24:mi') frdate, to_date('22/12/2007 10:53','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 13 row_id, 789087 client_id, 4 status, to_date('22/12/2007 10:53','dd/mm/yyyy hh24:mi') frdate, to_date('22/12/2007 11:51','dd/mm/yyyy hh24:mi') todate from dual union all
SELECT 14 row_id, 789087 client_id, 5 status, to_date('22/12/2007 11:51','dd/mm/yyyy hh24:mi') frdate, null from dual)
SELECT t1.*, DENSE_RANK () OVER (ORDER BY t1.client_id, t1.chg_status) rank_id
FROM (select client_id, status, prev_status, sum(case when nvl(prev_status,-1) != status then 1 else 0 end) over (partition by client_id order by frdate) chg_status, frdate, todate
from (
SELECT c.client_ID
, c.status
, lag(status) over (partition by client_id order by frdate) as prev_status
, c.frdate
, c.todate
FROM dat c
ORDER BY c.client_id, c.frdate)) t1
ORDER BY t1.client_id, t1.frdate
返回:
CLIENT_ID, STATUS, PREV_STATUS, CHG_STATUS, FRDATE, TODATE, RANK_ID
123456, 4, , 1, 20/12/2007 6:02:00 PM, 20/12/2007 6:07:00 PM, 1
123456, 4, 4, 1, 20/12/2007 6:07:00 PM, 20/12/2007 6:50:00 PM, 1
123456, 4, 4, 1, 20/12/2007 6:50:00 PM, 21/12/2007 10:38:00 AM, 1
123456, 4, 4, 1, 21/12/2007 10:38:00 AM, 21/12/2007 4:39:00 PM, 1
123456, 5, 4, 2, 21/12/2007 4:39:00 PM,, 2
789087, 4, , 1, 20/12/2007 6:02:00 PM,20/12/2007 6:07:00 PM, 3
789087, 4, 4, 1, 20/12/2007 6:07:00 PM,20/12/2007 6:50:00 PM, 3
789087, 4, 4, 1, 20/12/2007 6:50:00 PM, 21/12/2007 10:38:00 AM, 3
789087, 4, 4, 1, 21/12/2007 10:38:00 AM, 21/12/2007 5:54:00 PM, 3
789087, 4, 4, 1, 21/12/2007 5:54:00 PM, 21/12/2007 6:32:00 PM, 3
789087, 4, 4, 1, 21/12/2007 6:32:00 PM,22/12/2007 6:48:00 AM, 3
789087, 5, 4, 2, 22/12/2007 6:48:00 AM, 22/12/2007 10:53:00 AM, 4
789087, 4, 5, 3, 22/12/2007 10:53:00 AM, 22/12/2007 11:51:00 AM, 5
789087, 5, 4, 4, 22/12/2007 11:51:00 AM,, 6
答案 2 :(得分:0)
使用1
(下面的GRP列)标记每个客户的所有状态更改。
然后使用分析SUM函数添加这些数字:
with tab1 as (
select client_id,from_date, status,
nvl(lag(status) over (partition by client_id order by from_date),-1) status_lag,
case when (nvl(lag(status) over (partition by client_id order by from_date),-1) <> status) then
1 end grp
from tst
)
, tab2 as (
select client_id,from_date, status,status_lag, grp,
sum(grp) over (partition by client_id order by from_date) as RANK
from tab1
)
select * from tab2;
按预期给出
CLIENT_ID FROM_DATE STATUS STATUS_LAG GRP RANK
---------- ------------------- ---------- ---------- ---------- ----------
1001 01.10.2015 00:00:00 1 -1 1 1
1001 02.10.2015 00:00:00 1 1 1
1001 03.10.2015 00:00:00 2 1 1 2
1001 04.10.2015 00:00:00 2 2 2
1001 05.10.2015 00:00:00 3 2 1 3
1001 09.10.2015 00:00:00 1 3 1 4
1002 12.10.2015 00:00:00 1 -1 1 1
1002 13.10.2015 00:00:00 3 1 1 2
1002 15.10.2015 00:00:00 3 3 2
我的设置
create table tst
(client_id number,
from_date date,
status number);
insert into tst values (1001, to_date('01-10-15','dd-mm-rr'),1);
insert into tst values (1001, to_date('02-10-15','dd-mm-rr'),1);
insert into tst values (1001, to_date('03-10-15','dd-mm-rr'),2);
insert into tst values (1001, to_date('04-10-15','dd-mm-rr'),2);
insert into tst values (1001, to_date('05-10-15','dd-mm-rr'),3);
insert into tst values (1001, to_date('09-10-15','dd-mm-rr'),1);
insert into tst values (1002, to_date('12-10-15','dd-mm-rr'),1);
insert into tst values (1002, to_date('13-10-15','dd-mm-rr'),3);
insert into tst values (1002, to_date('15-10-15','dd-mm-rr'),3);
commit;
答案 3 :(得分:0)
以下是使用Tabibitosan的解决方案:
with client as (select 1 row_id, 123456 client_id, 4 status_id, to_date('20/12/2007 18:02','dd/mm/yyyy hh24:mi') from_date, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') todate from dual union all
select 2 row_id, 789087 client_id, 4 status_id, to_date('20/12/2007 18:02','dd/mm/yyyy hh24:mi') from_date, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') todate from dual union all
select 3 row_id, 789087 client_id, 4 status_id, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') from_date, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') todate from dual union all
select 4 row_id, 789087 client_id, 4 status_id, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') from_date, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') todate from dual union all
select 5 row_id, 123456 client_id, 4 status_id, to_date('20/12/2007 18:07','dd/mm/yyyy hh24:mi') from_date, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') todate from dual union all
select 6 row_id, 123456 client_id, 4 status_id, to_date('20/12/2007 18:50','dd/mm/yyyy hh24:mi') from_date, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') todate from dual union all
select 7 row_id, 123456 client_id, 4 status_id, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') from_date, to_date('21/12/2007 16:39','dd/mm/yyyy hh24:mi') todate from dual union all
select 8 row_id, 789087 client_id, 4 status_id, to_date('21/12/2007 10:38','dd/mm/yyyy hh24:mi') from_date, to_date('21/12/2007 17:54','dd/mm/yyyy hh24:mi') todate from dual union all
select 9 row_id, 789087 client_id, 4 status_id, to_date('21/12/2007 17:54','dd/mm/yyyy hh24:mi') from_date, to_date('21/12/2007 18:32','dd/mm/yyyy hh24:mi') todate from dual union all
select 10 row_id, 789087 client_id, 4 status_id, to_date('21/12/2007 18:32','dd/mm/yyyy hh24:mi') from_date, to_date('22/12/2007 06:48','dd/mm/yyyy hh24:mi') todate from dual union all
select 11 row_id, 123456 client_id, 5 status_id, to_date('21/12/2007 16:39','dd/mm/yyyy hh24:mi') from_date, null from dual union all
select 12 row_id, 789087 client_id, 5 status_id, to_date('22/12/2007 06:48','dd/mm/yyyy hh24:mi') from_date, to_date('22/12/2007 10:53','dd/mm/yyyy hh24:mi') todate from dual union all
select 13 row_id, 789087 client_id, 4 status_id, to_date('22/12/2007 10:53','dd/mm/yyyy hh24:mi') from_date, to_date('22/12/2007 11:51','dd/mm/yyyy hh24:mi') todate from dual union all
select 14 row_id, 789087 client_id, 5 status_id, to_date('22/12/2007 11:51','dd/mm/yyyy hh24:mi') from_date, null from dual)
select row_id,
client_id,
status_id,
from_date,
todate,
dense_rank() over (order by client_id, status_id, grp) rank_id
from (select row_id,
client_id,
status_id,
from_date,
todate,
row_number() over (order by client_id, from_date) - row_number() over (partition by status_id order by client_id, from_date) grp -- this is the tabibitosan step
from client) t1
order by client_id, from_date, status_id;
ROW_ID CLIENT_ID STATUS_ID FROM_DATE TODATE RANK_ID
---------- ---------- ---------- ---------------- ---------------- ----------
1 123456 4 20/12/2007 06:02 20/12/2007 06:07 1
5 123456 4 20/12/2007 06:07 20/12/2007 06:50 1
6 123456 4 20/12/2007 06:50 21/12/2007 10:38 1
7 123456 4 21/12/2007 10:38 21/12/2007 04:39 1
11 123456 5 21/12/2007 04:39 2
2 789087 4 20/12/2007 06:02 20/12/2007 06:07 3
3 789087 4 20/12/2007 06:07 20/12/2007 06:50 3
4 789087 4 20/12/2007 06:50 21/12/2007 10:38 3
8 789087 4 21/12/2007 10:38 21/12/2007 05:54 3
9 789087 4 21/12/2007 05:54 21/12/2007 06:32 3
10 789087 4 21/12/2007 06:32 22/12/2007 06:48 3
12 789087 5 22/12/2007 06:48 22/12/2007 10:53 5
13 789087 4 22/12/2007 10:53 22/12/2007 11:51 4
14 789087 5 22/12/2007 11:51 6