首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >time1 of day1与time2 day2之间的SQL周期选择

time1 of day1与time2 day2之间的SQL周期选择
EN

Stack Overflow用户
提问于 2017-10-11 11:32:07
回答 2查看 405关注 0票数 0

我在DB2里有一张这样的桌子:

  • 任务名称
  • 日期格式的tast_end_date
  • 时间格式的task_end_time

该表包含每天100多个记录,我必须构建一个查询来统计整个月从dayX的10:00到dayX+1的09:59:59结束的任务。

对我来说,结果应该是这样的,例如:

  • 时段01.01.2017时间10:00至02.01.2017时间09:59:59结束25项任务
  • 时段02.01.2017时间10:00至03.01.2017时间09:59:59结束25项任务
  • 期间03.01.2017时间10:00至04.01.2017时间09:59:59结束25项任务

所以这不是一个简单的日期选择,我必须同时使用日期和时间的范围。克拉拉兹

我用大海狸来选择。寻求帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-11 15:39:48

就我个人而言,我会构建时间戳,然后调整它,使时间落入一个日历日。那就是数一组日期的问题..。

就像这样

代码语言:javascript
运行
复制
with adj as (                                             
  select 
    timestamp(mydate, mytime)                          
      - 9 hours - 59 minutes - 59 seconds - 1 microsecond 
     as ts 
 from mytable                                                 
)                                                         
select month(ts), count(*) as nbr_tasks                   
from adj                                                  
group by month(ts)                                        
票数 0
EN

Stack Overflow用户

发布于 2017-10-11 17:33:59

假设您有一个日历表,如果您能够查询周/月/年(如果不能,您应该创建一个)。使用WHEREGROUP BY子句中的函数(包括日期数学)可以使索引的使用无效,这通常会导致查询速度变慢。相反,最好指定范围开始点/结束点,以便系统可以直接命中索引。

无论如何,让我们为我们的日期数据添加时间!

好吧,我们每天都试着分组,对吧?

代码语言:javascript
运行
复制
SELECT calendarDate as start
FROM CalendarTable
WHERE calendarDate >= :rangeStart
      AND calendarDate < :rangeEnd

..。好吧,好吧,这就让我们开始了,但是在查询的时候,结束,或者说,真正的,下一组的开始也是很有帮助的:

代码语言:javascript
运行
复制
SELECT calendarDate as start, calendarDate + 1 DAY as end
FROM CalendarTable
WHERE calendarDate >= :rangeStart
      AND calendarDate < :rangeEnd

所以约会就是这样..。但我们也需要增加时间!

幸运的是,这是一个常量值:

代码语言:javascript
运行
复制
SELECT calendarDate as startDate, TIME('10:00:00') as startTime
       calendarDate + 1 DAY as endDate, TIME('10:00:00') as endTime
FROM CalendarTable
WHERE calendarDate >= :rangeStart
      AND calendarDate < :rangeEnd

我们可以将其封装在子查询或CTE中,但是用于连接的实际条件是什么呢?

问题是检查或忽略日期所涉及的时间:

代码语言:javascript
运行
复制
task_end_date > startDate OR (task_end_date =  startDate AND task_end_time >= startTime)

..。至于上界:

代码语言:javascript
运行
复制
task_end_date < endDate OR (task_end_date = endDate AND task_end_time < endTime)

所以把它们放在一起看起来是这样的:

代码语言:javascript
运行
复制
WITH QueryRange AS (SELECT calendarDate as startDate, CAST('10:00:00' as TIME) as startTime,
                           calendarDate + 1 DAY as endDate, CAST('10:00:00' as TIME) as endTime
                    FROM CalendarTable
                    WHERE calendarDate >= :startRange
                          AND calendarDate < :endRange)
SELECT QueryRange.startDate, QueryRange.startTime, 
       QueryRange.endDate, QueryRange.endTime,
       TasksEnded.ended
FROM (SELECT QueryRange.startDate, COUNT(Tasks.task_name) as ended
      FROM QueryRange
      LEFT JOIN Tasks
             ON (Tasks.task_end_date > QueryRange.startDate 
                 OR (Tasks.task_end_date = QueryRange.startDate
                     AND Tasks.task_end_time >= QueryRange.startTime))
                AND (Tasks.task_end_date < QueryRange.endDate 
                     OR (Tasks.task_end_date = QueryRange.endDate 
                         AND Tasks.task_end_time < QueryRange.endTime))
      GROUP BY QueryRange.startDate) as TasksEnded
JOIN QueryRange 
  ON QueryRange.startDate = TasksEnded.startDate
ORDER BY QueryRange.startDate

小提琴例子 (忽略在不同关系数据库管理系统上工作的微小变化,原则是正确的)。

顺便提一句,如果您将日期/时间实际存储为单个时间戳,则这要简单得多。假设您的日历文件仍然只处理日期(它应该这样做),只需使用它来构造完整的时间戳,而不是分隔的字段:

代码语言:javascript
运行
复制
SELECT TIMESTAMP(calendarDate, '10:00:00') as rangeStart
       TIMESTAMP(calendarDate + 1 DAY, '10:00:00') as rangeEnd
FROM CalendarTable
WHERE calendarDate >= :rangeStart
      AND calendarDate < :rangeEnd

..。这使得查询只使用一对检查。

代码语言:javascript
运行
复制
LEFT JOIN Tasks
       ON Tasks.task_end_stamp >= QueryRange.rangeStart 
          AND Tasks.task_end_stamp < QueryRange.rangeEnd

……这几乎肯定会比分离字段所需的混合AND/OR更快。

因此,如果首先从起始数据构造时间戳,仍然可以按日期子字段进行查询和分组。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46687180

复制
相关文章

相似问题

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