DB2-SAS复杂情况

时间:2018-11-15 13:58:12

标签: sql sas db2

我正在努力缩短查询的执行时间。

我必须提取每月最后一天在开始日期和结束日期之间的行。

在我的表格中,数据是按周设置的 例如:从2018-11-11开始到2018-11-17开始,从2018-11-18开始到2018-11-24结束,依此类推。

我的查询如下:

select field1, field2,
max(case when '2018-01-31' between start and end then 1 else 0 end) as M1,
max(case when '2018-02-28' between start and end then 1 else 0 end) as M2,
....
max(case when '2018-12-31' between start and end then 1 else 0 end) as M12
from tableX
where start between '2018-01-01' and '2018-12-31'
group by field1, field2

所以我只想考虑包含月末的行。 知道我该如何改善吗?

我正在考虑在where子句中做类似的事情:

where '2018-01-31' between start and end
or '2018-02-28' between start and end
...
or '2018-12-31' between start and end

是否可以做这样的事情:

where ('2018-01-31','2018-02-28',....,'2018-12-31') between start and end

谢谢

弗朗克

2 个答案:

答案 0 :(得分:3)

取决于Db2版本和平台,功能LAST_DAY可以解决问题。考虑这样的事情:

where LAST_DAY(start) between start and end

答案 1 :(得分:0)

可接受的答案将处理的行数减到最少。

where LAST_DAY(start) between start and end

但是,这仍将处理您想要的年份以外的行。因此,您仍应使用边界条件。例如...

where LAST_DAY(start) between start and end
  and start between '2018-01-01' and '2018-12-31'

还有一个缺点,就是没有索引可以满足LAST_DAY()条件,并且将扫描表或索引。

使用您在注释中提供的信息,可以重新建立索引查找的使用。

每行始终为一个星期,从星期一开始。因此,对于任何给定的月末,如果我们回到星期一,我们将得到匹配的start

WHERE
    start IN (
        DATE_TRUNC(WEEK, LAST_DAY('2018-01-01')), -- find last day in jan, round down to Monday
        DATE_TRUNC(WEEK, LAST_DAY('2018-02-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-03-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-04-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-05-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-06-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-07-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-08-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-09-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-10-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-11-01')),
        DATE_TRUNC(WEEK, LAST_DAY('2018-12-01'))
    )

那要长得多。

可以通过使用日历表,带有日期列表和有关这些日期的元数据来帮助您快速搜索的日历表来减少这种情况。

现在,在start上创建索引,然后尝试上面的显式where子句。它应该比您到目前为止尝试的速度还要快。


编辑:

类似地,您可以编写CASE表达式是一种“更容易为人类阅读的方式” ...

MAX(CASE WHEN start = DATE_TRUNC(WEEK, LAST_DAY('2018-01-01')) THEN 1 ELSE 0 END)   AS M01