【问题标题】:issue with complex query involving returning 0 for no data in query result涉及在查询结果中没有数据返回 0 的复杂查询问题
【发布时间】:2012-01-26 11:35:33
【问题描述】:

我有一个像这样在 Oracle11g 架构中定义的表

Txn_summ_dec
=================
id 
currentdate
resource_id
user_id
trans_id
eventdescptn

每个资源都有不同的事件描述。 我给出了一个日期范围(最多 1 个月或更短)和 resource_id,我想获得给定资源 id 的所有用户的不同计数,按 currentdate 分组,eventdescptn

所以我有以下查询

SELECT COUNT(DISTINCT(txn_summ_dec.user_id)) as dusers, currentDate, eventdescptn
FROM Txn_summ_dec
WHERE resource_id = 1
AND currentdate BETWEEN TO_DATE('2011-12-01', 'YYYY-MM-DD') 
                    AND TO_DATE('2011-12-31', 'YYYY-MM-DD')
GROUP BY currentdate, eventdescptn

它正确地给了我下面的结果

dusers   currentdate            eventdescptn 
182      12/01/2011 00:00:00    Save 
33       12/04/2011 00:00:00    Save 
98       12/01/2011 00:00:00    Read
22       12/30/2011 00:00:00    Write

我想要以下格式的结果:
来自查询 给定的日期范围是假设一个月的 5 号到 5 号(或更少)我想要资源的所有 eventdescptn 范围内的所有日期的结果。 如果该范围内的特定日期没有结果,对于特定事件 descptn,那么它仍应在结果集中具有 'dusers' 值 = 0 的记录
因此,如果一个资源有 3 个不同的 eventdescptns(保存、读取、写入)并且日期范围是一个月的 5 日到 30 日,那么结果集中应该总共有 26X3 = 78 条记录。
我该如何为此编写查询? 另外,我稍后需要将其转换为休眠状态.. 但是从 Sql 开始就可以了 提前致谢

【问题讨论】:

  • 将存储的timestamp 列标记为'currentdate' 是错误 的事情 - 它应该被标记为event_occurred(它肯定不再是'current') .您将要创建一个包含描述的event 表,并且只存储ID。您将希望按时间戳的 DAY 分组,而不是按(至少)秒精度的东西进行分组。
  • 当然,更改列的名称对我来说很好,它只存储日期而不存储时间信息。您还建议使用临时表事件来获取结果吗?如果可以怎么办?
  • 不行,不是临时表,创建一个永久的event表,只在这个汇总表中存储id。此外,您是否确定您的currentdate 字段是日期类型 - 您在结果中包含时间 - 无论如何您可能需要时间用于记录目的。此外,范围比较的建议是最小包含,最大排除;所以AND currentDate >= TO_DATE('2011-12-01', 'YYYY-MM-DD') AND currentDate < TO_DATE('2011-12-01', 'YYYY-MM-DD') + INTERVAL 1 MONTH(在这里猜测oracle语法)。

标签: sql oracle11g


【解决方案1】:

在此处检查接受的答案: generate days from date range

如果我对您的理解正确,您不必在日志范围内的每个日期都有一个事件。该答案为您提供了一种实现范围内日期列表的方法。如果您可以修改它以包含每个事件中的每个日期中的 1 个,您只需重新加入您已经在此处聚合的结果并将空 dUsers 设置为零。

【讨论】:

    【解决方案2】:

    我还没有尝试过,但我想知道你是否可以这样做:

     WITH the_query AS (
          ... your query here ...
     )
     SELECT dusers, currentdate, eventdescptn 
       FROM the_query
      WHERE 0 != ( SELECT COUNT(*) FROM the_query )
     UNION
     SELECT 0, NULL, NULL
       FROM the_query
      WHERE 0 = ( SELECT COUNT(*) FROM the_query )
    

    【讨论】:

    • 鉴于 OP 想要所有日期的数据(在该范围内),不(因为您提供的是 null 日期)。我相当有信心该语句的后半部分不会返回任何内容,除非原始查询返回 0 结果。此外,如果它确实生成了“缺失”日期,那么您还没有给它任何终止条件——“无限”结果。
    猜你喜欢
    • 2019-02-17
    • 2014-08-03
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 2015-02-25
    • 1970-01-01
    相关资源
    最近更新 更多