【问题标题】:How to create a start and end date with no gaps from one date column and to sum a value within the dates如何创建一个日期列中没有间隔的开始日期和结束日期,并在日期内求和一个值
【发布时间】:2022-02-06 06:12:23
【问题描述】:

我是在 SQL 开发人员中使用的新 SQL 编码。

我有一个包含 4 列的表:患者 ID (ptid)、服务日期 (dt)、保险支付金额 (insr_amt)、自付费用金额 (op_amt)。 (见下表1)

我想做的是 (1) 使用“dt”列创建两列“start_dt”和“end_dt”,如果患者 ID 的日期没有间隔,则使用填充开始和结束日期患者 ID 的第一个和最后一个日期,但是如果患者 ID 中的服务日期存在差距,则为每个患者 ID 创建单独的开始和结束日期行,以及 (2) 将两个付款金额按患者 ID 相加在一组开始和结束日期访问中(见下表 2)。

在 SQL 开发人员中使用 SQL 代码运行此程序的方法是什么? 谢谢!

表 1:

Ptid dt insr_amt op_amt
A 1/1/2021 30 20
A 1/2/2021 30 10
A 1/3/2021 30 10
A 1/4/2021 30 30
B 1/6/2021 10 10
B 1/7/2021 20 10
C 2/1/2021 15 30
C 2/2/2021 15 30
C 2/6/2021 60 30

表 2:

Ptid start_dt end_dt total_insr_amt total_op_amt
A 1/1/2021 1/4/2021 120 70
B 1/6/2021 1/7/2021 30 20
C 2/1/2021 2/2/2021 30 60
C 2/6/2021 2/6/2021 60 30

【问题讨论】:

    标签: sql oracle date sum gaps-and-islands


    【解决方案1】:

    您没有提到具体的数据库,所以这个解决方案适用于 PostgreSQL。你可以这样做:

    select
      ptid,
      min(dt) as start_dt,
      max(dt) as end_dt,
      sum(insr_amt) as total_insr_amt,
      sum(op_amt) as total_op_amt
    from (
      select *,
        sum(inc) over(partition by ptid order by dt) as grp
      from (
        select *,
          case when dt - interval '1 day' = lag(dt) over(partition by ptid order by dt)
               then 0 else 1 end as inc
        from t
      ) x
    ) y
    group by ptid, grp
    order by ptid, grp
    

    结果:

     ptid  start_dt    end_dt      total_insr_amt  total_op_amt 
     ----- ----------  ----------  --------------  ----------- 
     A     2021-01-01  2021-01-04  120             70           
     B     2021-01-06  2021-01-07  30              20           
     C     2021-02-01  2021-02-02  30              60           
     C     2021-02-06  2021-02-06  60              30           
    

    请参阅DB Fiddle 1 的运行示例。

    为 Oracle 编辑

    根据要求,适用于 Oracle 的修改后的查询是:

    select
      ptid,
      min(dt) as start_dt,
      max(dt) as end_dt,
      sum(insr_amt) as total_insr_amt,
      sum(op_amt) as total_op_amt
    from (
      select x.*,
        sum(inc) over(partition by ptid order by dt) as grp
      from (
        select t.*,
          case when dt - 1 = lag(dt) over(partition by ptid order by dt)
               then 0 else 1 end as inc
        from t
      ) x
    ) y
    group by ptid, grp
    order by ptid, grp
    

    请参阅db<>fiddle 2 的运行示例。

    【讨论】:

    • 当我分解代码并一一运行每个子查询时,它就可以工作了。但是当我像上面那样运行它时,它似乎不喜欢按表达式顺序排列的 grp 变量。我收到错误:ORA-01791:不是 SELECTed 表达式 01791。00000 -“不是 SELECTed 表达式” *原因:*操作:第 18 行错误第 18 行第 18 行是“按 ptid、grp 排序”和列18 是 grp。这很奇怪,好像我独立运行子查询然后它就起作用了!谢谢!
    • 你没有指定数据库,所以这个例子在 PostgreSQL 中工作。
    • 查看 Oracle 数据库的解决方案。
    • 谢谢,是的,它适用于 Oracle 数据库!编辑工作!谢谢
    猜你喜欢
    • 2018-10-16
    • 2021-08-22
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多