Как поместить дело в выписку «Где» для Oracle SQL - PullRequest
0 голосов
/ 24 февраля 2020

Для запроса, приведенного ниже, я пытаюсь указать указанный диапазон дат c в зависимости от текущего дня месяца. Если это 20 или меньше (например, «2/7/2020»), то я хочу диапазон дат для января. В противном случае я хочу диапазон дат на февраль. Возможно ли это сделать с помощью описания случая? Или есть лучший способ?

SELECT
    account,
    start_date,
    amount
FROM
    table1
WHERE
    CASE
            WHEN (
                SELECT
                    CAST(EXTRACT(DAY FROM sysdate) AS NUMBER)
                FROM
                    dual
            ) <= 20 THEN
                    start_date
            BETWEEN '2020-01-01' AND '2020-01-31'
        ELSE start_date BETWEEN '2020-02-01' AND '2020-02-29'
    END

Ответы [ 6 ]

2 голосов
/ 24 февраля 2020

Вы можете сделать это, избегая оператора case и используя усечение даты - 20 до месяца, например:

SELECT account,
     start_date,
     amount
FROM   table1
WHERE  start_date >= TRUNC(SYSDATE - 20, 'mm')
AND    start_date < add_months(TRUNC(dt - 20, 'mm'), 1);

Если вам действительно нужно было использовать выражение CASE (вы не можете используйте оператор CASE в SQL), вам нужно сделать что-то вроде:

SELECT account,
     start_date,
     amount
FROM   table1
WHERE  start_date >= CASE WHEN to_char(SYSDATE, 'dd') <= '20' THEN add_months(TRUNC(SYSDATE, 'mm'), -1) ELSE TRUNC(SYSDATE, 'mm') END
AND    start_date < CASE WHEN to_char(SYSDATE, 'dd') <= '20' THEN TRUNC(SYSDATE, 'mm') ELSE add_months(TRUNC(SYSDATE, 'mm'), 1) END;

Примечание: если вы используете функцию, вам не нужно заключать ее в select .. from dual, вы можете использовать его непосредственно в операторе SQL.

Я также предположил, что вам нужен динамический диапазон c, например, если день месяца равен 20 или меньше, диапазон равен за предыдущий месяц, в противном случае текущий месяц.


ETA: Вы бы использовали два вышеупомянутых запроса, если в столбце start_date есть индекс, в противном случае вы можете просто сделать:

SELECT account,
     start_date,
     amount
FROM   table1
WHERE  TRUNC(start_date, 'mm') = TRUNC(SYSDATE - 20, 'mm');
1 голос
/ 24 февраля 2020

Операторы Case возвращают отдельные значения. Таким образом, вы должны вывести дату начала, и вам потребуются два утверждения.

select account, start_date, amount
from table1 where
start_date between 
(case
when (select cast(extract(day from sysdate) as number) from dual) <= 20 then '2020-01-01' 
else '2020-02-01'
end) and 
(case
when (select cast(extract(day from sysdate) as number) from dual) <= 20 then '2020-01-31' 
else '2020-02-29'
end)
0 голосов
/ 24 февраля 2020

Использование выражений CASE в качестве операндов МЕЖДУ:

SELECT account
     , start_date
     , amount
FROM table1
WHERE start_date BETWEEN CASE
                           WHEN extract(day from sysdate) <= 20
                             THEN trunc(sysdate -interval '1' month, 'month')
                             ELSE trunc(sysdate, 'month')
                         END
                     AND CASE
                           WHEN extract(day from sysdate) <= 20
                             THEN last_day(sysdate -interval '1' month)
                             ELSE last_day(sysdate)
                         END
0 голосов
/ 24 февраля 2020
    select account, amount, start_date
      from table1
     where (   (    (select cast (extract (day from sysdate) as number) from dual) <= 20
                    and start_date between date '2020-01-01' and date '2020-01-31')
            or (    (select cast (extract (day from sysdate) as number) from dual) > 20
                    and start_date between date '2020-02-01' and date '2020-02-29')
           );
0 голосов
/ 24 февраля 2020

Вы можете использовать оператор or с функцией last_day следующим образом:

Select * from your_table
Where (
       start_date <= trunc(sysdate,'mm') + 20
       and start_date between trunc(sysdate,'mm') - interval '1' month and trunc(sysdate,'mm') - 1
      )
   Or
      (
       start_date > trunc(sysdate,'mm') + 20 
       and start_date between trunc(sysdate, 'mm') and last_day(sysdate)
      )

Этот подход будет использовать индекс для start_date, если таковой имеется.

Приветствия !!

0 голосов
/ 24 февраля 2020

Один метод вычитает 20 дней, а затем получает границу месяца:

where start_date >= trunc(sysdate - interval '20' day, 'MON') and
      start_date < trunc(sysdate - interval '20' day, 'MON') + interval '1' month

Этот подход удобен для индекса (и разбиения) - можно использовать соответствующий индекс для start_date. Также безопасно, если start_date имеет компоненты времени.

Примечание. Вы можете использовать sysdate, не используя подзапрос.

...