TRASTACT SQL Caso su una lunghezza variabile input_expression
Domanda
Devo produrre un rapporto ad hoc sul numero di transazioni effettuate con diversi tipi di carta di credito. Ai fini del rapporto va bene supporre che tutte le carte di credito che iniziano con una 4 siano carte Visa e che quelle che iniziano con un 5 siano MasterCard.
Questa query funziona bene per le distinzioni di cui sopra:
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
Tuttavia, nella nostra situazione (non sono sicuro di come funzioni in tutto il mondo) tutte le carte che iniziano con un 3 possono essere considerate le carte del club dei Diners, tranne per quelle che iniziano con un 37 che sono carte Amex.
Estensione della query sopra come questa sembra un hack completo
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
Esiste un modo elegante di raggrupparsi dalla prima cifra in tutti i casi, tranne in cui le prime due cifre corrispondono al caso speciale?
Inoltre non ho idea di come farlo Titolo Questa domanda se qualcuno vuole dare una mano ...
MODIFICARE: Avevo i valori per MasterCard e Visa mescolati, quindi solo per essere corretti :)
Soluzione
Puoi fare dichiarazioni casi come le seguenti:
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
Altri suggerimenti
Non sono sicuro del tuo sistema, ma nelle espressioni di Oracle Case sono esattamente questo, quindi puoi nidirle:
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
Potresti semplicemente archiviare la colonna del tipo di carta nella tua tabella e FK su una tabella del tipo di carta o provare qualcosa come:
CASE
WHEN LEFT(pan,2)='37' then ...
WHEN LEFT(pan,1)='3' then ...
.....
MODIFICARE
Dovresti davvero prendere in considerazione la memorizzazione di un valore del tipo di carta in una tabella. Determinalo una volta quando si inserisce e quindi è possibile interrogare i dati senza saltare attraverso questi cerchi ogni volta. Ti proteggerai anche se l'algoritmo cambia ad un certo punto, tutti i dati esistenti saranno corretti
Personalmente, penso che il tuo modo "longhand" sia elegante in quanto è facile da leggere e mantenere di quanto troverei la risposta @samjudson (ma vedo l'appello del loro approccio). Potresti usare OR
per testare più di un valore per caso. io trovo LIKE
più facile da leggere ma questo potrebbe essere solo io;) ad es.
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