Использование вычисления в операторе Case — Oracle SQL

#sql #oracle #case

#sql #Oracle #случай

Вопрос:

Привет мастерам sql и волшебникам,

Я пытаюсь рассчитать дни SLA на основе определенного параметра (case-type). Для каждого типа обращения дни SLA рассчитываются немного по-разному. Мой вопрос: использую ли я ОПЕРАТОР CASE для достижения этого? Я запишу то, что у меня есть до сих пор, что не работает:

 fifthlevel --with statement declaring sla days
AS (SELECT

     CASE sla_days
     WHEN fourthlevel.case_type = 'Complaint'
     THEN sla_days =

      ( SELECT COUNT (*)
        FROM (SELECT business_date
              FROM ( SELECT TO_DATE ('01-01-2011', 'dd-mm-yyyy')   LEVEL - 1
                               business_date
                     FROM DUAL
                     CONNECT BY LEVEL <=
                                 TO_DATE ('31-12-2099', 'dd-mm-yyyy')
                               - TO_DATE ('01-01-2011', 'dd-mm-yyyy')
                                 1) date_tab1
                     WHERE TO_CHAR (business_date, 'DY') NOT IN ('SAT', 'SUN')
                     AND business_date NOT IN (SELECT holiday_dt
                                               FROM cisadm.ci_cal_hol
                                               WHERE calendar_cd = 'WAW01'
                                              )
                   ) work_days1
             WHERE work_days1.business_date > fourthlevel.correspondence_date
             AND work_days1.business_date <= fourthlevel.close_date
             )
     WHEN fourthlevel.case_type = 'Enquiry'
     THEN sla_days = (SELECT COUNT (*)
                      FROM (SELECT business_date
                            FROM (SELECT TO_DATE ('01-01-2011',
                                                   'dd-mm-yyyy')
                                              LEVEL
                                            - 1
                                               business_date
                                   FROM DUAL
                                   CONNECT BY LEVEL <=TO_DATE('31-12-2099',
                                                                'dd-mm-yyyy')
                                                      TO_DATE('01-01-2011',
                                                              'dd-mm-yyyy')  1
                                  ) date_tab1
                            WHERE TO_CHAR (business_date, 'DY') 
                                  NOT IN ('SAT', 'SUN')
                             AND business_date 
                                  NOT IN (SELECT holiday_dt
                                          FROM cisadm.ci_cal_hol
                                          WHERE calendar_cd = 'WAW01'
                                         )
                            ) work_days1
                      WHERE work_days1.business_date > fourthlevel.agreed_Date
                        AND work_days1.business_date <=
                               fourthlevel.close_date
                     )
     END
    FROM fourthlevel,

    fourthlevel.* --also wanting to select * from preceding WITH statement
    FROM fourthlevel)
  

Хорошо, это выглядит немного запутанно, но, по сути, я пытаюсь получить два разных вычисления на основе типов case_types ‘Жалоба’ и ‘Запрос’.

Кто-нибудь может указать мне правильное направление?

Дайте мне знать, если я могу предоставить какую-либо дополнительную информацию.

Легенды!

Комментарии:

1. Привет, ребята, спасибо за ответы, извините, я пока не могу проголосовать. Также интересно, буду ли я использовать CASE, если я хочу иметь поле, в котором указано, были ли дни sla в пределах порогового значения. Т. Е. Одно поле, которое указывает, являются ли sla_days меньше 15, а другое поле, которое указывает, являются ли sla_days меньше 20. Это было бы что-то вроде: case when sla_days <=15 then 'Under SLA" WHEN sla_days > 15 then 'Exceeds SLA'

Ответ №1:

Извлеките подзапрос work_days1 как отдельный cte:

 , work_days1 as (
SELECT business_date
       FROM (    SELECT TO_DATE ('01-01-2011', 'dd-mm-yyyy')   LEVEL - 1
                           business_date
                   FROM DUAL
             CONNECT BY LEVEL <=
                             TO_DATE ('31-12-2099', 'dd-mm-yyyy')
                           - TO_DATE ('01-01-2011', 'dd-mm-yyyy')
                             1) date_tab1
      WHERE     TO_CHAR (business_date, 'DY') NOT IN ('SAT', 'SUN')
            AND business_date NOT IN (SELECT holiday_dt
                                        FROM cisadm.ci_cal_hol
                                       WHERE calendar_cd = 'WAW01')),
fifthlevel --with statement declaring sla days
 AS (SELECT
 CASE 
 WHEN fourthlevel.case_type = 'Complaint'
 THEN (SELECT COUNT(*) FROM work_days1 WHERE
 work_days1.business_date > fourthlevel.correspondence_date
    AND work_days1.business_date <= fourthlevel.close_date)
 WHEN fourthlevel.case_type = 'Enquiry'
 THEN sla_days = (SELECT COUNT (*) work_days1 WHERE
 work_days1.business_date > fourthlevel.agreed_Date
                    AND work_days1.business_date <=
                           fourthlevel.close_date) END as sla_days, * 
      FROM fourthlevel)
  

Комментарии:

1. Ваше решение также отлично подходит для случаев, когда мне нужно использовать совершенно разные вычисления для каждого типа обращения. Спасибо за ваш вклад.

Ответ №2:

Кажется, что единственным различием между двумя case_type является условие work_days1.business_date . Итак, вы можете сжать запрос следующим образом:

 fifthlevel --with statement declaring sla days
AS (
SELECT
  COUNT (*) sla_days
FROM
  (
    SELECT
      business_date
    FROM
      (
        SELECT
          TO_DATE ('01-01-2011', 'dd-mm-yyyy')   LEVEL- 1 business_date
        FROM
          DUAL
          CONNECT BY LEVEL <= TO_DATE ('31-12-2099','dd-mm-yyyy') - TO_DATE ('01-01-2011','dd-mm-yyyy')   1
      )
      date_tab1
    WHERE TO_CHAR (business_date, 'DY') NOT IN ('SAT', 'SUN')
    AND business_date NOT IN (SELECT holiday_dt FROM cisadm.ci_cal_hol WHERE calendar_cd = 'WAW01')
  )
  work_days1 INNER JOIN fourthlevel
ON
  work_days1.business_date > (
    CASE
      WHEN fourthlevel.case_type = 'Complaint' THEN fourthlevel.correspondence_date
      WHEN fourthlevel.case_type = 'Enquiry' THEN fourthlevel.agreed_Date
    END)
AND work_days1.business_date <= fourthlevel.close_date;
  

Комментарии:

1. Ваше решение идеально подходит для того, что мне нужно, однако оно давало мне неправильные sla_days. Удаление внутреннего соединения и вложение оператора CASE в предложение WHERE исправили это для меня. Какова была причина создания внутреннего соединения?

2. Я вижу, что work_days1 и fourthlevel соединяются с использованием условий (например, work_days1.business_date > fourthlevel.agreed_Date ). Поэтому я явно создал ВНУТРЕННЕЕ СОЕДИНЕНИЕ.