Длинное утверждение CASE - написано ли оно настолько эффективно, насколько это возможно? - PullRequest
1 голос
/ 24 апреля 2019

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

Все было выполнено в Access до того, как я начал, так что это моя попытка переместить большие отчеты в SQL.

Хранимая процедура работает нормально, но существует множество каналов продаж, которые определяются другими частями данных, и, таким образом, именно здесь появляется оператор CASE. Некоторые данные извлекаются как каналы, которых я не ожидаю и в целом это просто очень долго, так что я не знаю, может ли это выглядеть аккуратно? это может быть что-то простое, например, добавление скобок, но я в значительной степени самоучка в SQL, и я стремлюсь приобрести хорошие привычки и учиться у других, чтобы видеть!

CASE 
        WHEN mop = 0
            AND Channel = 'Internet'
            AND financeinstal = 10
            THEN 'Finance option 10 months'
        WHEN mop = 0
            AND Channel = 'Internet'
            AND financeinstal = 4
            THEN 'Finance option 4'
        WHEN Channel = 'Corporate'
            OR pb = 'PR Department'
            THEN 'Corporate'
        WHEN Channel = 'Call Centre'
            OR username = 'call centre'
            AND mop = 3
            OR mop = 4
            THEN 'Call Centre'
        WHEN Channel = 'Internet'
            AND username = 'InternetUser'
            AND mop = 3
            OR mop = 4
            THEN 'Internet'
        WHEN Channel = 'Premium'
            OR Channel = 'Premium Office'
            THEN 'Premium'
        WHEN Channel = 'Ticket Office'
            AND MOP = 1
            OR MOP = 2
            OR MOP = 3
            OR MOP = 4
            THEN 'Ticket Office (Full Payment)'
        WHEN mop_desc = 'Direct Debit'
            AND mop = 8
            THEN 'Automatic'
        WHEN Channel = 'Ticket'
            THEN 'Ticket'
        ELSE 'Other'
        END AS Sales_Channel

Итак, я ожидаю, что результаты будут такими, как я положил их в дело, но, например, некоторые, которые я ожидал бы вернуть, так как Интернет возвращается как Call Center

Ответы [ 3 ]

5 голосов
/ 24 апреля 2019

Я почти уверен, что у вас есть ошибки. Вы должны использовать круглые скобки, когда пропускаете and и or. Или, еще лучше, используйте in.

Например:

WHERE Channel = 'Internet' AND
      username = 'InternetUser' AND
      mop = 3 OR
      mop = 4

вероятно должно быть:

WHERE Channel = 'Internet' AND
      username = 'InternetUser' AND
      mop IN (3, 4)
1 голос
/ 24 апреля 2019

вы должны быть в состоянии переписать оператор case как соединение со встроенной таблицей, что будет быстрее

например, первые 2 оператора case могут быть переписаны следующим образом

with lookup(mop,channel,finance,return)
AS
(
   SELECT 0, 'Internet', 10, 'Finance option 10 months'
   UNION ALL
   SELECT 0, 'Internet', 4, 'Finance option 4'
)
SELECT 
 -- etc
 -- instead of case
 L.return 
 -- etc
FROM base
JOIN lookup AS L on base.mop = L.mop AND base.Channel = L.channel AND base.financeinstal = L.finance
0 голосов
/ 24 апреля 2019

AND имеет более высокий приоритет оператора, чем OR. Таким образом, при отсутствии скобок AND оцениваются вместе, а затем OR.

Думайте о приоритете оператора как о том, насколько липкими будут условия, если не использовать круглые скобки. Итак, с этим:

Chanel = 'Internet' AND Username = 'InternetUser' AND mop = 3 OR mop = 4`

Это слипается:

Chanel = 'Internet' AND Username = 'InternetUser' AND mop = 3

Так что OR mop = 4 идет сам по себе:

Chanel = 'Internet' AND Username = 'InternetUser' AND mop = 3
OR 
mop = 4

Вышеуказанное оценивается следующим образом, если выражено в явных скобках:

(Chanel = 'Internet' AND Username = 'InternetUser' AND mop = 3)
OR 
mop = 4

Но это приведет к неверному результату, также с условием без скобок. Поэтому вам нужно поставить круглые скобки в нужных местах, чтобы исправить ваше состояние:

Chanel = 'Internet' AND Username = 'InternetUser' AND (mop = 3 OR mop = 4)

В SQL есть сокращение для OR, когда вы хотите сравнить поле со многими значениями. Это оператор IN, он не только полезен, когда у вас есть много значений для сравнения с полем, он также полезен, когда вы хотите минимизировать использование скобок. Поэтому вместо OR используйте IN:

Chanel = 'Internet' AND Username = 'InternetUser' AND mop IN (3,4)

AND имеет более высокий приоритет, чем OR, а затем IN имеет более высокий приоритет, чем AND, поэтому вышеприведенное не оценивается как:

(Chanel = 'Internet' AND Username = 'InternetUser' AND mop) IN (3,4)

Вместо этого сначала оценивается IN, а затем AND. Таким образом, он оценивается следующим образом, когда явно написано в скобках:

Chanel = 'Internet' AND Username = 'InternetUser' AND (mop IN (3,4))

Поскольку IN имеет более высокий приоритет, чем AND, скобка вокруг mop IN (3,4) может быть безопасно удалена:

Chanel = 'Internet' AND Username = 'InternetUser' AND mop IN (3,4)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...