首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在sql查询中计算治疗天数

在sql查询中计算治疗天数
EN

Stack Overflow用户
提问于 2015-03-30 15:53:23
回答 4查看 301关注 0票数 3

我正试着从甲骨文数据库中按月计算治疗天数。(大大简化的)数据如下:

代码语言:javascript
复制
 Therapies                          
+-----------+-----------+----------+
| Rx Number | StartDate | StopDate |
|-----------+-----------+----------|
| 1         | 12-29-14  | 1-10-15  |
| 2         | 1-2-15    | 1-14-15  |
| 3         | 1-29-15   | 2-15-15  |
+-----------+-----------+----------+

就本例而言,所有时间都假定为午夜。治疗总天数为(10-1 + 32-29) + (14-2) + (15-1 + 32-29) = 41。1月份治疗总天数为(10-1) + (14-2) + (32-29) = 24。

如果我想计算1月份的治疗天数,我最大的努力是以下查询:

代码语言:javascript
复制
SELECT SUM(stopdate - startdate) 
FROM therapies 
WHERE startdate > to_date('01-JAN-15') 
  AND stopdate < to_date ('01-FEB-15');

然而,rx的1和3根本没有被捕获。我可以尝试以下几种方法:

代码语言:javascript
复制
SELECT SUM(stopdate - startdate) 
FROM therapies 
WHERE stopdate > to_date('01-JAN-15') 
  AND startdate < to_date ('01-FEB-15');

但这将包括第一次和第三次治疗的全部持续时间,而不仅仅是一月份的部分。为了使问题更加复杂,我需要这些为期两年的每月摘要。所以我的问题是:

  1. 如何包括悬垂疗法,以便只包括目标时间段内的部分,以及
  2. 我如何在两年期间自动生成这些每月摘要?
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-03-30 19:04:34

如何将悬垂疗法包括在内,以便只包括目标时间段内的部分?

代码语言:javascript
复制
select sum(
    greatest(least(stopdate, date '2015-01-31' + 1) 
      - greatest(startdate, date '2015-01-01'), 0)) suma
  from therapies

我如何在两年期间自动生成这些每月摘要?

代码语言:javascript
复制
with period as (select date '2014-01-01' d1, date '2015-12-31' d2 from dual),
months as (select trunc(add_months(d1, level-1), 'Month') dt 
    from period connect by add_months(d1, level-1)<d2)
select to_char(dt, 'yyyy-mm') mth, 
    sum(greatest(least(stopdate, add_months(dt, 1)) - greatest(startdate, dt), 0)) suma
  from therapies, months
  group by to_char(dt, 'yyyy-mm') order by mth

上面的查询产生了所需的输出。请将您的日期插入适当的位置,以更改分析期间。在第二个SQL子查询中,months给出了24个日期,每个月一个。剩下的只是使用函数greatest()least()和一些数学。

票数 2
EN

Stack Overflow用户

发布于 2015-03-30 16:16:23

使用case语句设置开始日期和停止日期。如下所示:

select sum( Stopdate - (case Startdate when startdate < to_date(@YourBeginingDate) then To_date(@YourBeginingDate) else startdate end) FROM therapies WHERE stopdate > to_date(@YourBeginingDate) AND StartDate < to_date(@YourEndingDate)

票数 1
EN

Stack Overflow用户

发布于 2015-03-30 16:16:42

我要做的事情如下:

代码语言:javascript
复制
WITH t1 AS (
  SELECT 1 AS rx, DATE'2014-12-29' AS start_date
       , DATE'2015-01-10' AS stop_date
    FROM dual
   UNION ALL
  SELECT 2, DATE'2015-01-02', DATE'2015-01-14'
    FROM dual
   UNION ALL
  SELECT 3, DATE'2015-01-29', DATE'2015-02-15'
    FROM dual
)
SELECT TRUNC(rx_dt, 'MONTH') AS rx_month, SUM(rx_cnt) AS rx_day_cnt
  FROM (
    SELECT rx_dt, COUNT(*) AS rx_cnt
      FROM (
        SELECT rx, start_date + LEVEL - 1 AS rx_dt
          FROM t1
       CONNECT BY start_date + LEVEL - 1 < stop_date
           AND PRIOR rx = rx
           AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
    ) GROUP BY rx_dt
) GROUP BY TRUNC(rx_dt, 'MONTH')
 ORDER BY rx_month

结果:

代码语言:javascript
复制
12/1/2014 12:00:00 AM   2
1/1/2015 12:00:00 AM    24
2/1/2015 12:00:00 AM    15

See SQL Fiddle here.

我所做的是使用LEVELCONNECT BY来获得所有基于start_datestop_date的治疗(不包括在内)。然后,我GROUP BY治疗日期(rx_dt),以处理重叠疗法。然后我使用GROUP BY函数来确定治疗的月份。

这应该可以在两年(或更长时间)内正常工作;只需在上一次GROUP BY之前添加该过滤器即可。

代码语言:javascript
复制
WHERE rx_dt >= DATE'2014-01-01'
  AND rx_dt < DATE'2016-01-01'
GROUP BY TRUNC(rx_dt, 'MONTH')

注意,如果您的主键是复合的,则应该在CONNECT BY子句中包含所有列:

代码语言:javascript
复制
CONNECT BY start_date + LEVEL - 1 < stop_date
    AND PRIOR rx = rx
    AND PRIOR patient_id = patient_id
    --etc.
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29350704

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档