Sql where子句中如何正确使用case

Sql where子句中如何正确使用case,sql,oracle,plsql,Sql,Oracle,Plsql,所以我有一个过程,我目前正在调试,我已经把它缩小到这个select语句 注:其中,截止日期(“”),33005220是参数的表示形式 现在,我们要做的是,取一个参数,它是一个时间戳,然后减去一个偏移值 偏移量是自星期日午夜=0的一周开始以来经过的分钟数。(因此,如果是周一午夜,偏移量将=1440) 当从参数中减去偏移量时,就得到了一周的开始。然后从已经预先确定的表中获取偏移量值,并将该值添加到周初以获得时间戳 这样做是为了获得班次的开始日期和结束日期 我的原始代码在下面没有问题,但是它缺少周六到

所以我有一个过程,我目前正在调试,我已经把它缩小到这个select语句

注:其中,截止日期(“”),33005220是参数的表示形式

现在,我们要做的是,取一个参数,它是一个时间戳,然后减去一个偏移值

偏移量是自星期日午夜=0的一周开始以来经过的分钟数。(因此,如果是周一午夜,偏移量将=1440)

当从参数中减去偏移量时,就得到了一周的开始。然后从已经预先确定的表中获取偏移量值,并将该值添加到周初以获得时间戳

这样做是为了获得班次的开始日期和结束日期

我的原始代码在下面没有问题,但是它缺少周六到周日的边界条件

SELECT SHIFT_ID_PK, SHIFT_NAME_FK,
         SHIFT_START_DAY, SHIFT_START_TIME,
         SHIFT_END_DAY, SHIFT_END_TIME, 
         SITE_ID_FK, SHIFT_DAY_ID,
         STARTOFFSET, ENDOFFSET,
         TO_TIMESTAMP_TZ(TO_CHAR((PSTARTTIMESTAMP - (VSTARTOFFSET  / 24 / 60)) + (STARTOFFSET / 24 / 60), 'YYYY-MM-DD HH:MI:SS AM'),  'YYYY-MM-DD HH:MI:SS AM TZH:TZM') as SHIFT_START_DATE,
         TO_TIMESTAMP_TZ(TO_CHAR((PENDTIMESTAMP -  (VENDOFFSET / 24 / 60)) + (ENDOFFSET   / 24 / 60), 'YYYY-MM-DD HH:MI:SS AM') ,'YYYY-MM-DD HH:MI:SS AM TZH:TZM') as SHIFT_END_DATE
  from   shift_tbl
  WHERE
         ENDOFFSET >= VSTARTOFFSET
  and    STARTOFFSET < VENDOFFSET 
  order by shift_start_date asc;
选择SHIFT\u ID\u PK、SHIFT\u NAME\u FK、,
班次开始日期,班次开始时间,
班次结束日,班次结束时间,
站点ID\u FK,轮班日ID,
开始偏移,结束偏移,
将时间戳(TO_CHAR((PSTARTTIMESTAMP-(VSTARTOFFSET/24/60))+(STARTOFFSET/24/60)、“YYYY-MM-DD HH:MI:SS AM”)、“YYYY-MM-DD HH:MI:SS AM TZH:TZM”)作为班次开始日期,
至时间戳(至字符((PENDTIMESTAMP-(VENDOFFSET/24/60))+(ENDOFFSET/24/60),“YYYY-MM-DD HH:MI:SS AM”),“YYYY-MM-DD HH:MI:SS AM TZM”)作为班次结束日期
从班次
哪里
ENDOFFSET>=VSTARTOFFSET
和STARTOFSET<偏移量
按班次\开始\日期asc订购;
现在,我已经提出了处理这个边界条件的方法,我已经在脚本中测试过了

   declare
  VSTARTOFFSET integer;
  VENDOFFSET integer;
  SHIFTOFFSET integer;
  PSTARTTIMESTAMP timestamp;
  PENDTIMESTAMP timestamp;
  begin 
    VSTARTOFFSET := 10020;
    VENDOFFSET := 420; 
    PSTARTTIMESTAMP := TO_DATE('3/17/2012 23:00', 'mm/dd/yyyy hh24:mi');
    PENDTIMESTAMP :=   TO_DATE('3/18/2012 7:00', 'mm/dd/yyyy hh24:mi');

  SELECT SHIFT_ID_PK, SHIFT_NAME_FK,
         SHIFT_START_DAY, SHIFT_START_TIME,
         SHIFT_END_DAY, SHIFT_END_TIME, 
         SITE_ID_FK, SHIFT_DAY_ID,
         STARTOFFSET, ENDOFFSET,
         TO_TIMESTAMP_TZ(TO_CHAR((PSTARTTIMESTAMP - (VSTARTOFFSET / 24 / 60)) + (STARTOFFSET / 24 / 60), 'YYYY-MM-DD HH:MI:SS AM'),'YYYY-MM-DD HH:MI:SS AM TZH:TZM') as SHIFT_START_DATE,  
         TO_TIMESTAMP_TZ(TO_CHAR((PENDTIMESTAMP- (VENDOFFSET / 24 / 60)) + (ENDOFFSET   / 24 / 60), 'YYYY-MM-DD HH:MI:SS AM'),'YYYY-MM-DD HH:MI:SS AM TZH:TZM') AS SHIFT_END_DATE
  from   SHIFT_TBL
  where
    case 
      when SHIFT_START_DAY = 7 and  SHIFT_END_DAY = 1 then          
                 SHIFTOFFSET:= ENDOFFSET + 10080; 
          and    VENDOFFSET := VENDOFFSET + 10080;
      else
                 SHIFTOFFSET := ENDOFFSET;
    end
                 SHIFTOFFSET >= VSTARTOFFSET
          and    STARTOFFSET < VENDOFFSET 
    order by SHIFT_START_DATE asc; 
  end;
声明
VSTARTOFFSET整数;
偏移量整数;
shiftofset整数;
PSTARTTIMESTAMP时间戳;
时间戳;
开始
VSTARTOFFSET:=10020;
偏移量:=420;
PSTARTTIMESTAMP:=截止日期('2012年3月17日23:00','mm/dd/yyyy hh24:mi');
PENDTIMESTAMP:=截止日期('2012年3月18日7:00','mm/dd/yyyy hh24:mi');
选择SHIFT\U ID\U PK、SHIFT\U NAME\U FK、,
班次开始日期,班次开始时间,
班次结束日,班次结束时间,
站点ID\u FK,轮班日ID,
开始偏移,结束偏移,
将时间戳(TO_CHAR((PSTARTTIMESTAMP-(VSTARTOFFSET/24/60))+(STARTOFFSET/24/60)、“yyy-MM-DD HH:MI:SS AM”)、“YYYY-MM-DD HH:MI:SS AM TZH:TZM”)作为班次开始日期,
至时间戳(至字符((PENDTIMESTAMP-(VENDOFFSET/24/60))+(ENDOFFSET/24/60),“YYYY-MM-DD HH:MI:SS AM”),“YYYY-MM-DD HH:MI:SS AM TZM”)作为班次结束日期
从班次
哪里
案例
当班次开始日=7,班次结束日=1时
shiftofset:=ENDOFFSET+10080;
和VENDOFFSET:=VENDOFFSET+10080;
其他的
shiftofset:=内偏移;
结束
shiftofset>=VSTARTOFFSET
和STARTOFSET<偏移量
按班次\开始\日期asc订购;
结束;
如您所见,我不确定如何处理where子句中的case语句。基本上,我想做的是,如果开始日是星期六,结束日是星期天,那么将10080(一周)添加到结束偏移量/销售偏移量,如果不满足该条件,则使用原始值

基本上,我的问题相当简单……我相信,但我很难找到解决方案。所以我想知道的是如何在where子句中正确使用case语句。如果我不打算在where子句中使用这种形式的case语句,那么我应该如何设置这个select语句呢

非常感谢您的帮助或建议。
谢谢。

与其在WHERE子句中设置变量,我建议将一个基本查询放入游标中,并使用它来驱动循环中的主查询。这将允许您为每个迭代设置查询外部的变量。它看起来像这样:

declare
--variables
cursor c_shifts is
select SHIFT_ID_PK, SHIFT_START_DAY, SHIFT_END_DAY
from SHIFT_TBL;
begin
for r_result in c_shifts
loop
if r_result.SHIFT_START_DAY = 1 and r_result.SHIFT_END_DAY = 7 then
  --set variables to values for special case shifts
else
  --set variables for all other cases
end if;
   --run your query for the particular result in this loop iteration based upon r_result.SHIFT_ID_PK, using the variables you set above
   --save results to a staging table, directly dbms_output from the block, etc., as needed
end loop;
   --commit results if saving to a staging table, etc., as needed once the loop completes
end;

与其尝试在WHERE子句中设置变量,我建议将基本查询放入游标中,并使用它在循环中驱动主查询。这将允许您为每个迭代设置查询外部的变量。它看起来像这样:

declare
--variables
cursor c_shifts is
select SHIFT_ID_PK, SHIFT_START_DAY, SHIFT_END_DAY
from SHIFT_TBL;
begin
for r_result in c_shifts
loop
if r_result.SHIFT_START_DAY = 1 and r_result.SHIFT_END_DAY = 7 then
  --set variables to values for special case shifts
else
  --set variables for all other cases
end if;
   --run your query for the particular result in this loop iteration based upon r_result.SHIFT_ID_PK, using the variables you set above
   --save results to a staging table, directly dbms_output from the block, etc., as needed
end loop;
   --commit results if saving to a staging table, etc., as needed once the loop completes
end;

您不需要在WHERE子句中设置任何变量,实际上即使您不能这样做。 您要做的是编写正确的逻辑谓词(即返回true或false的表达式)来描述要获取的行

以下是我将如何定义它的两个示例(据我了解,您的需求):

  • 没有案例:

    WHERE
    ( SHIFT_START_DAY = 7 and  SHIFT_END_DAY = 1  AND ENDOFFSET + 10080 >= VSTARTOFFSET and STARTOFFSET < VENDOFFSET + 10080) OR
    ( NOT (SHIFT_START_DAY = 7 and  SHIFT_END_DAY = 1) AND SHIFTOFFSET >= VSTARTOFFSET and STARTOFFSET < VENDOFFSET )
    
    在哪里
    (班次开始日=7,班次结束日=1,内偏移+10080>=VSTARTOFFSET和STARTOFFSET=VSTARTOFFSET和STARTOFFSET
  • 关于案例:

    WHERE
    (CASE WHEN SHIFT_START_DAY = 7 and  SHIFT_END_DAY = 1 THEN ENDOFFSET + 10080 ELSE ENDOFFSET END) >= VSTARTOFFSET
    AND    STARTOFFSET < (CASE WHEN SHIFT_START_DAY = 7 and  SHIFT_END_DAY = 1 THEN VENDOFFSET + 10080 ELSE VENDOFFSET END)
    
    在哪里
    (班次开始日=7,班次结束日=1,则ENDOFFSET+10080,否则ENDOFFSET END)>=VSTARTOFFSET
    和STARTOFSET<(班次开始日=7,班次结束日=1,则VENDOFFSET+10080,否则VENDOFFSET结束)
    

  • 我没有调试此表达式,因此不希望它们工作;),但是我希望您已经有了这个想法。

    您不需要在WHERE子句中设置任何变量,实际上即使您不能这样做。 您要做的是编写正确的逻辑谓词(即返回true或false的表达式)来描述要获取的行

    以下是我将如何定义它的两个示例(据我了解,您的需求):

  • 没有案例:

    WHERE
    ( SHIFT_START_DAY = 7 and  SHIFT_END_DAY = 1  AND ENDOFFSET + 10080 >= VSTARTOFFSET and STARTOFFSET < VENDOFFSET + 10080) OR
    ( NOT (SHIFT_START_DAY = 7 and  SHIFT_END_DAY = 1) AND SHIFTOFFSET >= VSTARTOFFSET and STARTOFFSET < VENDOFFSET )
    
    在哪里
    (班次开始日=7,班次结束日=1,内偏移+10080>=VSTARTOFFSET和STARTOFFSET