如何找到 sql 中患者订购的药物之间的差距?
How to find the Gap between medicine ordered by the patients in sql?
这是输入Table
id name disease drug ship date supply
1 aa D1 dd 10-05-2020 30
1 aa D1 dd 07-06-2020 30
1 aa D1 dd 12-07-2020 30
1 aa D1 dd 09-08-2020 30
1 aa D1 dd 07-09-2020 28
1 aa D1 dd 11-10-2020 28
1 aa D1 dd 10-11-2020 28
2 bb D2 cd 01-01-2020 10
2 bb D2 cd 06-01-2020 10
这是所需的输出。(预计日期,late/early,根据提到的条件有差距)
id name disease drug ship date supply expected date late/early Gap
1 aa D1 dd 10-05-2020 30 null first order 0
1 aa D1 dd 07-06-2020 30 09-06-2020 early 0
1 aa D1 dd 12-07-2020 30 09-07-2020 late 3
1 aa D1 dd 09-08-2020 30 11-08-2020 early 0
1 aa D1 dd 07-09-2020 28 08-09-2020 early 0
1 aa D1 dd 11-10-2020 28 6-10-2020 late 5
1 aa D1 dd 10-11-2020 28 08-11-2020 late 2
2 bb D2 cd 01-01-2020 10 null first order 0
2 bb D2 cd 06-01-2020 10 11-01-2020 early 5
- id,name,disease,drug,shipdate,supply 已给定字段
- 第一个订单日期是 10-05-2020 如果我们添加供应 (30) 我们得到我们的下一个预期日期,即 09-06-2020(我已经在下一行显示它以计算差距)但是病人有他在 07-06-2020 下了第二个订单,比预期早(所以它是提前补货,因此缺口为 0),在这种情况下,下一个预期日期是之前的预期日期(09-06-2020)+供应(30)即 09-07-2020.
- 他在 12-07-2020 第三次订购,延迟了 3 天,所以这是一个延迟补货,在这种情况下,下一个预计日期是发货日期(12-07-2020)+供应(30) 即 11-08-2020。
- 简而言之,如果是提前补货,那么下一个预计日期是之前的预计日期 + 供应,如果是延迟补货,则为发货日期 + 供应。
- 注意:- 主要目的是计算差距。
这是使用 Oracle 12.1 中引入的 match_recognize
子句的解决方案。
测试数据:
alter session set nls_date_format = 'dd-mm-yyyy';
create table input_table(id, name, disease, drug, ship_date, supply) as
select 1, 'aa', 'D1', 'dd', to_date('10-05-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('07-06-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('12-07-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('09-08-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('07-09-2020'), 28 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('11-10-2020'), 28 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('10-11-2020'), 28 from dual union all
select 2, 'bb', 'D2', 'cd', to_date('01-01-2020'), 10 from dual union all
select 2, 'bb', 'D2', 'cd', to_date('06-01-2020'), 10 from dual
;
查询:
with
prep (id, name, disease, drug, ship_date, supply, e_date, cls, exp_date) as (
select id, name, disease, drug, ship_date, supply, e_date, cls,
case cls when 'A' then lag(e_date + supply)
over (partition by id, disease, drug
order by ship_date)
else e_date end as exp_date
from input_table
match_recognize(
partition by id, disease, drug
order by ship_date
measures a.ship_date + sum(supply) - supply as e_date,
classifier() as cls
all rows per match
pattern (a b*)
define b as ship_date <= a.ship_date + sum(supply) - supply
)
)
select id, name, disease, drug, ship_date, supply, exp_date,
case when exp_date is null then 'first order'
when cls = 'A' then 'late'
else 'early' end as late_or_early,
case cls when 'A' then ship_date - exp_date end as gap
from prep
order by id, disease, drug, ship_date
;
输出:
ID NAME DISEASE DRUG SHIP_DATE SUPPLY EXP_DATE LATE_OR_EARLY GAP
-- ---- ------- ---- ---------- ---------- ---------- ------------- ---
1 aa D1 dd 10-05-2020 30 first order
1 aa D1 dd 07-06-2020 30 09-06-2020 early
1 aa D1 dd 12-07-2020 30 09-07-2020 late 3
1 aa D1 dd 09-08-2020 30 11-08-2020 early
1 aa D1 dd 07-09-2020 28 10-09-2020 early
1 aa D1 dd 11-10-2020 28 08-10-2020 late 3
1 aa D1 dd 10-11-2020 28 08-11-2020 late 2
2 bb D2 cd 01-01-2020 10 first order
2 bb D2 cd 06-01-2020 10 11-01-2020 early
这是输入Table
id name disease drug ship date supply
1 aa D1 dd 10-05-2020 30
1 aa D1 dd 07-06-2020 30
1 aa D1 dd 12-07-2020 30
1 aa D1 dd 09-08-2020 30
1 aa D1 dd 07-09-2020 28
1 aa D1 dd 11-10-2020 28
1 aa D1 dd 10-11-2020 28
2 bb D2 cd 01-01-2020 10
2 bb D2 cd 06-01-2020 10
这是所需的输出。(预计日期,late/early,根据提到的条件有差距)
id name disease drug ship date supply expected date late/early Gap
1 aa D1 dd 10-05-2020 30 null first order 0
1 aa D1 dd 07-06-2020 30 09-06-2020 early 0
1 aa D1 dd 12-07-2020 30 09-07-2020 late 3
1 aa D1 dd 09-08-2020 30 11-08-2020 early 0
1 aa D1 dd 07-09-2020 28 08-09-2020 early 0
1 aa D1 dd 11-10-2020 28 6-10-2020 late 5
1 aa D1 dd 10-11-2020 28 08-11-2020 late 2
2 bb D2 cd 01-01-2020 10 null first order 0
2 bb D2 cd 06-01-2020 10 11-01-2020 early 5
- id,name,disease,drug,shipdate,supply 已给定字段
- 第一个订单日期是 10-05-2020 如果我们添加供应 (30) 我们得到我们的下一个预期日期,即 09-06-2020(我已经在下一行显示它以计算差距)但是病人有他在 07-06-2020 下了第二个订单,比预期早(所以它是提前补货,因此缺口为 0),在这种情况下,下一个预期日期是之前的预期日期(09-06-2020)+供应(30)即 09-07-2020.
- 他在 12-07-2020 第三次订购,延迟了 3 天,所以这是一个延迟补货,在这种情况下,下一个预计日期是发货日期(12-07-2020)+供应(30) 即 11-08-2020。
- 简而言之,如果是提前补货,那么下一个预计日期是之前的预计日期 + 供应,如果是延迟补货,则为发货日期 + 供应。
- 注意:- 主要目的是计算差距。
这是使用 Oracle 12.1 中引入的 match_recognize
子句的解决方案。
测试数据:
alter session set nls_date_format = 'dd-mm-yyyy';
create table input_table(id, name, disease, drug, ship_date, supply) as
select 1, 'aa', 'D1', 'dd', to_date('10-05-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('07-06-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('12-07-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('09-08-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('07-09-2020'), 28 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('11-10-2020'), 28 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('10-11-2020'), 28 from dual union all
select 2, 'bb', 'D2', 'cd', to_date('01-01-2020'), 10 from dual union all
select 2, 'bb', 'D2', 'cd', to_date('06-01-2020'), 10 from dual
;
查询:
with
prep (id, name, disease, drug, ship_date, supply, e_date, cls, exp_date) as (
select id, name, disease, drug, ship_date, supply, e_date, cls,
case cls when 'A' then lag(e_date + supply)
over (partition by id, disease, drug
order by ship_date)
else e_date end as exp_date
from input_table
match_recognize(
partition by id, disease, drug
order by ship_date
measures a.ship_date + sum(supply) - supply as e_date,
classifier() as cls
all rows per match
pattern (a b*)
define b as ship_date <= a.ship_date + sum(supply) - supply
)
)
select id, name, disease, drug, ship_date, supply, exp_date,
case when exp_date is null then 'first order'
when cls = 'A' then 'late'
else 'early' end as late_or_early,
case cls when 'A' then ship_date - exp_date end as gap
from prep
order by id, disease, drug, ship_date
;
输出:
ID NAME DISEASE DRUG SHIP_DATE SUPPLY EXP_DATE LATE_OR_EARLY GAP
-- ---- ------- ---- ---------- ---------- ---------- ------------- ---
1 aa D1 dd 10-05-2020 30 first order
1 aa D1 dd 07-06-2020 30 09-06-2020 early
1 aa D1 dd 12-07-2020 30 09-07-2020 late 3
1 aa D1 dd 09-08-2020 30 11-08-2020 early
1 aa D1 dd 07-09-2020 28 10-09-2020 early
1 aa D1 dd 11-10-2020 28 08-10-2020 late 3
1 aa D1 dd 10-11-2020 28 08-11-2020 late 2
2 bb D2 cd 01-01-2020 10 first order
2 bb D2 cd 06-01-2020 10 11-01-2020 early