как правильно использовать case в предложении where - PullRequest
0 голосов
/ 20 марта 2012

Итак, у меня есть процедура, которую я сейчас нахожусь в процессе отладки, и я сузил ее до этого оператора select.

Примечание: где to_date (''), 3300, 5220 - это представление того, что будет получено из параметра.

Теперь, что это должно сделать, это взять параметр, который является временной меткой, и вычесть значение смещения

смещение - это количество прошедших минутс начала недели, когда воскресенье в полночь = 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;

Теперь, что я придумала для обработки этой границыусловие ниже того, что я тестировал в скрипте.

   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;

Как вы можете видеть, я не уверен, как обрабатывать оператор case внутри предложения where.По сути, я пытаюсь сделать так: если начальный день - суббота, а конечный день - воскресенье, то добавьте 10080 (одну неделю) к конечному смещению / смещению продавца, и если оно не соответствует этому условию, используйте исходные значения.

По сути, мой вопрос довольно прост ... я верю, но мне трудно найти решение.Так что я хотел бы знать, как правильно использовать оператор case внутри предложения where.И если я не собираюсь использовать оператор case в этой форме в предложении where, как именно я бы настроил этот оператор select.

Любая помощь или предложения приветствуются.Спасибо.

Ответы [ 3 ]

3 голосов
/ 21 марта 2012

Вам не нужно устанавливать какие-либо переменные в предложении WHERE, на самом деле даже вы не можете этого сделать. Вам нужно написать правильный логический предикат (то есть выражение, возвращающее true или false), описывающий строки, которые вы хотите получить.

Вот 2 примера того, как я бы попытался определить его (насколько я понимаю ваши требования):

  1. без ДЕЛА:

    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 )
    
  2. с CASE:

    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)
    

Я не отлаживал эти выражения, поэтому не ожидайте, что они будут работать;), но я надеюсь, что у вас есть идея.

0 голосов
/ 21 марта 2012

Не рассчитывать, запрос :)

Предложение: рассмотрите возможность использования вспомогательной календарной таблицы

Почему я должен рассмотреть возможность использования вспомогательной календарной таблицы?

Календарная таблица может значительно облегчить разработку решений вокруг любая бизнес-модель, которая включает даты. Последний раз я проверял, это включает в себя практически любую бизнес-модель, которую вы можете придумать, для некоторых степень. Постоянные проблемы, требующие многословия, К сложным и неэффективным методам относятся следующие вопросы:

  • Сколько рабочих дней между x и y?

  • Каковы все даты между вторым вторником марта и первой пятницей апреля?

  • ...

... возможно с столбцом для юлианизированных рабочих дней .

0 голосов
/ 21 марта 2012

Вместо того, чтобы пытаться установить переменные в предложении 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...