如何从给定日期范围下降的db中选择行?

时间:2017-07-07 10:49:18

标签: sql oracle

表格结构:

ID   VersionID   ShiftType   Duration(Hr)   FromDate       ToDate
**********************************************************************
1    1           WORKING     12             20150702        20170528
2    1           WORKING     12             20150702        20170528
3    2           NOTWORKING  06             20170529        20170531
4    2           WORKING     06             20170529        20170531
5    2           NOTWORKING  06             20170529        20170531
6    2           WORKING     06             20170529        20170531
7    3           WORKING     08             20170601        0
8    3           NOTWORKING  08             20170601        0
9    3           WORKING     08             20170601        0

在这里你可以看到我有3个版本(1,2,3)的班次(如10天的白班和接下来20天的夜班等)。

目前的跟随班次将没有结束时间(第7,8和9行)。

例如,从20150702到20170528,我跟随版本1,总共24小时(1天),两班制工作,从20170529到20170531跟随版本2,四班制两个工作和两个非工作总共24小时(1天) )。

现在,如果用户提供日期范围,我应该在该日期范围内进行转换。

提供日期范围:从20170528到20170614。

预期结果:所有行。

使用以下查询:

SELECT * FROM SHIFTS
WHERE (FFROMDATE >= 20170528 AND FFROMDATE <= 20170614) OR (FTODATE >= 20170528 AND FTODATE <= 20170614)

但不起作用:从20170502到20170514。

预期结果:第1,2行(但未选中)。

但不起作用:从20170604到20170714。

预期结果:第7,8,9行(但未选中)。

谢谢。

3 个答案:

答案 0 :(得分:1)

我们正在寻找3种截然不同的东西:

“查找完全包含在我的日期范围内的所有轮班”:

(FFROMDATE <= @StartDate AND FTODATE >= @EndDate)

查找与开始重叠的所有班次

(FFROMDATE >= @StartDate AND FFROMDATE <= @EndDate)

查找与结尾重叠的所有班次

(FTODATE >= @StartDate AND FTODATE <= @EndDate)

然后将它们组合成一个查询。

SELECT * FROM SHIFTS
WHERE
(FFROMDATE < @StartDate AND FTODATE > @EndDate) OR
(FFROMDATE >= @StartDate AND FFROMDATE <= @EndDate) OR
(FTODATE >= @StartDate AND FTODATE <= @EndDate)

请务必使用边界值对其进行测试,然后移除=以符合您的具体要求。

答案 1 :(得分:1)

这适用于所有三种情况:

select * 
  from shifts
  where fromdate <= range_end 
    and range_start <= case when todate = 0 then 99991231 else todate end

测试:

with shifts (id, fromdate, todate) as (
    select 1, 20150702, 20170528 from dual union all
    select 2, 20150702, 20170528 from dual union all
    select 3, 20170529, 20170531 from dual union all
    select 4, 20170529, 20170531 from dual union all
    select 5, 20170529, 20170531 from dual union all
    select 6, 20170529, 20170531 from dual union all
    select 7, 20170601,        0 from dual union all
    select 8, 20170601,        0 from dual union all
    select 9, 20170601,        0 from dual ),
ranges (range_id, range_start, range_end) as (
    select 1, 20170528, 20170614 from dual union all
    select 2, 20170502, 20170514 from dual union all
    select 3, 20170604, 20170714 from dual )
select * 
  from shifts cross join ranges
  where fromdate <= range_end 
    and range_start <= case when todate = 0 then 99991231 else todate end
  order by range_id, id

答案 2 :(得分:0)

oracle的解决方案:

org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g

对于SQL服务器:

您可以使用ISNULL或CASE代替NVL。我没有尝试使用sql server,因为我没有。