DB2:显示从上周六开始的7天,包括将来的几天

时间:2015-02-17 16:09:02

标签: sql db2 dayofweek

到目前为止:

此查询:

SELECT to_char(creationdate, 'DD-MM-YY') AS DATE
    ,sum(CASE 
            WHEN internalpriority >= 3
                THEN 1
            ELSE 0
            END) AS

CLOSE
FROM incident
WHERE creationdate BETWEEN (
                SELECT DISTINCT (CURRENT_timestamp - (DAYOFWEEK(CURRENT_timestamp) - 0) DAYS - (hour(current_timestamp)) hours - (minute(current_timestamp)) minute) AS MONDAY_OF_CURRENT_WEEK_DATE
                FROM incident
                )
        AND (
                SELECT DISTINCT (CURRENT_timestamp - (DAYOFWEEK(CURRENT_timestamp) - 6) DAYS - (hour(current_timestamp)) hours - (minute(current_timestamp)) minute) AS MONDAY_OF_CURRENT_WEEK_DATE
                FROM incident
                )
GROUP BY to_char(creationdate, 'DD-MM-YY')

得到了我这个结果(今天是17日,所以14日是上周六,到目前为止都很好)

14-02-15    307
15-02-15    296
16-02-15    687
17-02-15    357

但我也需要

18-02-15     0
19-02-15     0
20-02-15     0

未来哪一个,但是如何......

2 个答案:

答案 0 :(得分:0)

我强迫它,它有效,评论,如果你知道一个更优雅的方式,他们已经开始称我为弗兰肯斯坦博士在这里:(

select distinct to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 0 days ), 'DD-MM-YY') as date, count(ticketid) from incident where to_char(creationdate, 'DD-MM-YY') = to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 0 days ), 'DD-MM-YY')
union
select distinct to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 1 days), 'DD-MM-YY') as date, count(ticketid) from incident where to_char(creationdate, 'DD-MM-YY') = to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 1 days ), 'DD-MM-YY')
union
select distinct to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 2 days ), 'DD-MM-YY') as date, count(ticketid) from incident where to_char(creationdate, 'DD-MM-YY') = to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 2 days ), 'DD-MM-YY')
union
select distinct to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 3 days ), 'DD-MM-YY') as date, count(ticketid) from incident where to_char(creationdate, 'DD-MM-YY') = to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 3 days ), 'DD-MM-YY')
union
select distinct to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 4 days ), 'DD-MM-YY') as date, count(ticketid) from incident where to_char(creationdate, 'DD-MM-YY') = to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 4 days ), 'DD-MM-YY')
union
select distinct to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 5 days ), 'DD-MM-YY') as date, count(ticketid) from incident where to_char(creationdate, 'DD-MM-YY') = to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 5 days ), 'DD-MM-YY')
union
select distinct to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 6 days ), 'DD-MM-YY') as date, count(ticketid) from incident where to_char(creationdate, 'DD-MM-YY') = to_char((current_timestamp - ( DAYOFWEEK(CURRENT_timestamp)) DAYS + 6 days ), 'DD-MM-YY')

答案 1 :(得分:0)

首先,如果你正在处理时间戳,don't use BETWEEN。作为一个积极的,连续的范围类型,包含上限将产生不正确的结果(博客文章专门关于SQL Server和日期/时间/时间戳类型,但问题实际上是由于数字的表示方式)。

接下来,您尝试按天分组,但通过强制转换为字符会阻止数据库使用索引来完成查询的这一部分。

所以我们想要的是一个范围查询。我们将使用递归CTE来构建要使用的日期集,但您也可以使用日历表(向下移动,可能是最好的分析表来构建)。

WITH Date_Range AS (SELECT start AS incidentDate, 1 AS daysElapsed,
                           TIMESTAMP(start) AS dayStart, 
                           TIMESTAMP(start + 1 DAY) AS dayEnd
                    FROM (VALUES(CURRENT_DATE
                                  - (DAYOFWEEK_ISO(CURRENT_DATE) + 1) DAYS)) T(start)
                    UNION ALL
                    SELECT incidentDate + 1 DAY, daysElapsed + 1, 
                           dayEnd, dayEnd + 1 DAY
                    FROM Date_Range
                    WHERE daysElapsed < 7)

SELECT incidentDate, COUNT(Incident.internalPriority) AS close
FROM Date_Range
LEFT JOIN Incident
       ON Incident.internalPriority >= 3
          AND Incident.creationDate >= Date_Range.dayStart
          AND Incident.creationDate < Date_Range.dayEnd
GROUP BY incidentDate

(未经测试,因为我缺少一个可以反对的DB2实例。但是应该很接近)

请注意:

  • 我使用DAYOFWEEK_ISO(...),因为香草DAYOFWEEK(...)根据当前的文化背景给出了不同的结果(即,您显然希望星期日为1,但许多非美国文化使用星期一作为一周的第一天......)。这样做可以消除这个潜在的问题 哦,如果目前是星期六,它仍然会回溯一周,我认为这是预期的行为。
  • 代码假定creationDate是绝对(UTC)时间戳,而不是本地时间戳(带有时区)。如果情况并非如此,则需要进行更改。

<小时/> 您的原始查询存在以下问题:

SUM(CASE WHEN internalPriority >= 3
         THEN 1
         ELSE 0 END)

...有时,这种事情是获取此信息的唯一途径。问题是它可能需要进行表扫描(db需要读取internalPriority的所有值才能运行CASE)。通常最好将其设置为连接或其他过滤条件,这样可以通过索引进行检查(假设您有可以使用的东西)。

SELECT DISTINCT (CURRENT_timestamp - (DAYOFWEEK(CURRENT_timestamp) - 0) DAYS - (HOUR(current_timestamp)) HOURS - (MINUTE(current_timestamp)) MINUTE) AS MONDAY_OF_CURRENT_WEEK_DATE
FROM Incident

......好的:

  1. 您浏览表中的每个行,在每一行上执行日期数学运算(返回一个常量结果),然后由于DISTINCT而将大部分数据丢弃。哎哟。如果您需要单行,可以使用VALUES(...)或现有的单行虚拟表(sysibm/sysdummy1)构建它。
  2. 您错过了秒和小数秒。行将最终分配到错误的日期。值得庆幸的是,从CURRENT_TIMESTAMP返回的类型忽略了DST /时区(实质上是它的UTC),或者您使用该寄存器的事实可能会改变您所看到的那一天。

    BETWEEN

  3. 请不要使用它。对于除 count 整数之外的任何内容,您需要一个独占的上限(< - 表示正值)或一个独占的下限(> - 负值)。不要将它与整数一起使用以保持一致性。

    GROUP BY TO_CHAR(creationdate, 'DD-MM-YY')
    

    ...正如我已经提到的,对函数调用的结果进行分组将阻止DB使用索引来完成查询。尽可能避免这样的行为(无论如何格式化都是显示层代码中的事情)。