Transact SQL CASE с переменной длины input_expression - PullRequest
0 голосов
/ 06 августа 2009

Я должен подготовить специальный отчет о количестве транзакций, совершенных с различными типами кредитных карт. Для целей отчета можно предположить, что все кредитные карты, начинающиеся с 4, являются картами VISA, а те, которые начинаются с 5, являются MasterCard.

Этот запрос хорошо работает для вышеуказанных различий:

select card_type = 
    case substring(pan,1,1) 
        when '4' then 'VISA'
        when '5' then 'MasterCard'
        else 'unknown' 
    end,count(*),
    sum(amount)
from transactions
group by card_type

Однако в нашей ситуации (не знаю, как это работает во всем мире) все карты, начинающиеся с 3, могут считаться картами Diners Club, кроме тех, которые начинаются с 37, которые являются картами AMEX.

Расширение вышеуказанного запроса выглядит как полный взлом

select card_type = 
    case substring(pan,1,2) 
        when '30' then 'Diners'
        ...
        when '37' then 'AMEX'
        ...
        when '39' then 'Diners'
        when '40' then 'VISA'
        ...
        when '49' then 'VISA'
        when '50' then 'MasterCard'  
        ...
        when '59' then 'MasterCard'  
        else 'unknown' 
    end,count(*),
    sum(amount)
from transactions
group by card_type

Существует ли элегантный способ группировки по первой цифре во всех случаях, кроме случаев, когда первые две цифры соответствуют специальному случаю?

Я также понятия не имею, как Заголовок этот вопрос, если кто-то хочет помочь ...

РЕДАКТИРОВАТЬ : я перепутал значения для MasterCard и VISA, поэтому, чтобы быть точным:)

Ответы [ 4 ]

5 голосов
/ 06 августа 2009

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

select case
    when substring(pan,1,2) = '37' then 'AMEX'
    when substring(pan,1,1) = '3' then 'Diners'
    when substring(pan,1,1) = '4' then 'Mastercard'
    when substring(pan,1,1) = '5' then 'VISA'
    else 'unknown' 
end,
count(*),
sum(amount)
from transactions
group by card_type
2 голосов
/ 06 августа 2009

Не уверен насчет вашей системы, но в Oracle CASE выражения именно такие, поэтому вы можете их вкладывать:

case substring(pan,1,1)
        when '3' then case substring(pan,2,1)
                             when '7' then 'Amex'
                             else 'Diners'
                      end
        when '4' then 'VISA'
        when '5' then 'MasterCard'  
        else 'unknown'
end
1 голос
/ 21 января 2011

Лично я думаю, что ваш «длинный» способ элегантен в том смысле, что его легче читать и поддерживать, чем я нашел бы ответ @samjudson (но я вижу привлекательность их подхода). Вы можете использовать OR для проверки более одного значения в каждом случае. Мне легче читать LIKE, но это может быть только я;) Например,

CASE
   WHEN card_type LIKE '37%' 
      THEN 'AMEX'
   WHEN (
         card_type LIKE '30%' 
         OR card_type LIKE '39%' 
        )  
      THEN 'Diners'
   WHEN (
         card_type LIKE '40%' 
         OR card_type LIKE '49%' 
        ) 
      THEN 'VISA'
   WHEN (
         card_type LIKE '50%' 
         OR card_type LIKE '59%' 
        ) 
      THEN 'MasterCard'  
   ELSE 
      'unknown' 
END
1 голос
/ 06 августа 2009

Вы можете просто сохранить столбец типа карты в своей таблице и FK в таблице типа карты или попробовать что-то вроде:

CASE
    WHEN LEFT(pan,2)='37' then ...
    WHEN LEFT(pan,1)='3' then ...
    .....

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...