【问题标题】:Oracle SUM Values based on multiple Timestamps基于多个时间戳的 Oracle SUM 值
【发布时间】:2021-10-20 11:26:06
【问题描述】:

我遇到了一些问题,我无法真正解决问题。

我有一张表,其中包含通气持续时间的时间戳,其中包含患者通气的不同发作的整个持续时间(以分钟为单位)以及一些其他数据 + 患者病例 ID 的密钥。

这是一个表格示例:

PK CaseID Duration Begin End
1 1 45860 2018-01-13 12:15:00 2018-02-14 08:35:00
2 1 132 2018-01-11 11:45:00 2018-01-13 12:15:00

因此,如您所见,一个案例可以在此表中包含多行。 现在在另一张表中,我有患者/病例在住院期间(从入院到出院)所在的科室和工作站——还有时间戳:

PK CaseID Begin End StationID
1 1 2018-01-13 11:53:00 2018-01-13 12:11:00 123
2 1 2018-01-13 12:11:00 2018-02-18 10:59:00 123
3 1 2018-02-25 09:15:00 2018-02-26 11:27:00 123
4 1 2018-02-26 11:27:00 2018-03-01 10:04:00 123
5 1 2018-03-01 11:06:00 2018-03-03 14:25:00 234

现在我想构建一个查询来总结特定站点的通风持续时间。如您所见,我在第一个表中没有电台参考,因此我必须比较时间戳以获取我们在此特定电台上的时间(例如 - 像这里一样 - ID 为 123)。

我想我的逻辑是通风的开始必须大于或等于车站访问的开始,而结束必须小于或等于车站访问的结束,但我是不知道如何处理多次入住(例如重新入住时)。

我想出了以下查询,它似乎有效,但我认为数字有点偏低:

@set start_date = '01.01.2018 00:00:00'
@set end_date = '31.08.2021 23:59:59'
@set format = 'DD.MM.YYYY HH24:MI:SS'

SELECT 
    "Year",
    SUM("Ventilation Duration") AS "Sum"
FROM 
    (SELECT 
        f.CASEID AS "FallID",
        SUM(DECODE(fb.DURATION, 20 , ROUND(fb.DURATION / 60, 0), 21, fb.DURATION)) AS "Ventilation Duration",
        TO_CHAR(fa.BEGIN, 'DD.MM.YYYY HH24:MI') AS "Begin Station Stay",
        TO_CHAR(fb.BEGIN, 'DD.MM.YYYY HH24:MI') AS "Begin Ventilation",
        TO_CHAR(fb.END, 'DD.MM.YYYY HH24:MI') AS "End Ventilation",
        TO_CHAR(fa.END, 'DD.MM.YYYY HH24:MI') AS "End Station Stay",
        oe.STATION_NAME AS "Station",
        TO_CHAR(f.DISCHARGE_DATE, 'YYYY') AS "YEAR"
    FROM 
        CASE_VENTLATION fb
    INNER JOIN 
        CASE_STAY fa ON fa.CASEID = fb.CASEID
    INNER JOIN 
        CASE f ON f.CASEID = fb.CASEID 
    INNER JOIN 
        STATION oe ON oe.STATIONID = fa.STATIONID
    WHERE 
        f.STORNO_DATUM IS NULL 
        AND f.DISCHARGE_DATE BETWEEN TO_DATE(:start_date, :format) AND TO_DATE(:end_date, :format)
        AND fa.STATIONID = 10097
        AND f.CASEMARK IN (38140, 38142)
        AND fb.BEGIN >=(SELECT MIN(fa.BEGIN)FROM CASE_STAY fa2 WHERE fa2.CASEID = fb.CASEID AND fa2.STATION_ID = fa.STATION_ID)
        AND fb.END <= SELECT MAX(fa.ENDE)FROM CASE_STAY fa2 WHERE fa2.CASEID = fb.CASEID AND  fa2.STATION_ID = fa.STATION_ID)
    GROUP BY
        ...
    )
GROUP BY "Year"
ORDER BY "Year"

您是否认为这在逻辑上是正确的,或者我可以写一个更好的 WHERE-Condition - 尤其是使用 MIN 和 MAX 函数。

不要介意别名,我从德语翻译了一些字段名称,以便更容易理解它们引用的示例中的字段。

编辑:根据要求,这是我目前的结果:

Year Sum
2018 23412
2019 35618
2020 25633
2021 19682

问题是,正如我所说,它有点偏低,我想我错过了一些由于时间戳重叠:/。

非常感谢任何帮助!

谢谢!

【问题讨论】:

  • 您真的在使用 oracle 吗?那些是什么?在我看来它像 sql server
  • 我使用 Oracle 和 DBeaver 作为 DBMS。 @set 让您可以定义可以在语句中使用的变量,因此如果您有子查询或许多 UNION 语句,则不必一遍又一遍地定义它们。
  • 谢谢你的回答,我问是因为它看起来像 SQL Server 的 TSQL 中的 sql 变量
  • 为什么不能直接使用CaseID 呢? CaseID 不是与特定患者相关联吗?对于预期的患者,可能会或可能不会重叠的各种时间戳的存储可能是一个设计问题。您将如何处理不与第一个表中的行重叠的时间范围?
  • 嗨,Max,guten 标签。您能否使用您从该测试数据中提取的结果更新查询?

标签: sql database oracle


【解决方案1】:

说实话,我不完全确定我是否正确完成了任务,但它似乎很有趣,所以我会尝试。对不起,如果我错了。

如果您只需要计算患者在每个站点的通气时间,这就是我所拥有的:

select st.station_id, 
      v.caseid,
      sum((least(v.end_date, st.end_date) - greatest(v.begin_date, st.begin_date)) * 24 * 60) vent_duration_mins
 from vent v
 join dep_stat st
   on v.caseid = st.caseid
  and v.begin_date < st.end_date 
  and v.end_date > st.begin_date
group by st.station_id,          
         v.caseid                

这种情况假设所有日期列都是日期类型,而不是时间戳

db_fiddle

【讨论】:

  • 这似乎很合乎逻辑,我没有想到最小和最大。下周我回去工作时会试试看:)。也许我只是把事情复杂化了,因为我在这个问题上花了几个小时。无论如何感谢您的帮助!可能我稍后也会得到一个小提琴。
  • 凯因问题。让我知道是否有帮助
  • Hab's mal auf dem Homeoffice Laptop probiert, scheint zu funktionieren! Kannst du mir noch erklären wie du auf das LEAST und GREATEST kamst? Danke nochmal! :)
  • @Max 我会继续用英语。我也可以德语,但我们是社区的英文版。 LEAST 从给定的参数列表中获取最少的参数。而且由于我们需要从通气结束日期或患者不再住院的日期中获取最短日期,这是使用此功能的正确方法。对于最伟大的人来说也是如此。恰恰相反:它从给定的参数中取最大值。
  • 是的,我阅读了有关这些功能的 Oracle 文档,但您的解释是有道理的。我根据自己的需要对查询进行了一些修改,它似乎给出了正确的值。所以再次感谢你拯救了我这周剩下的时间:D
猜你喜欢
  • 1970-01-01
  • 2019-02-25
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
相关资源
最近更新 更多