2009-08-06 7 views
0

Ich muss einen Ad-hoc-Bericht über die Anzahl der Transaktionen mit verschiedenen Kreditkarten-Typen erstellen. Für die Zwecke des Berichts ist es gut anzunehmen, dass alle Kreditkarten, die mit einer 4 beginnen, VISA-Karten sind und dass diejenigen, die mit einer 5 beginnen, MasterCard sind.Transact SQL CASE über eine variable Länge input_expression

Diese Abfrage funktioniert gut für die oben genannten Unterschiede:

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 

aber in unserer Situation (nicht sicher, wie das weltweit funktioniert), um alle Karten, die mit einem 3 beginnen mit Ausnahme des Diner Club-Karten in Betracht gezogen werden, dass Beginnen Sie mit einer 37, die AMEX-Karten sind.

Erweiterung der obigen Abfrage wie folgt wie ein komplettes Hack scheint

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 

Gibt es eine elegante Art und Weise der Gruppierung durch die erste Ziffer in allen Fällen, außer denen die ersten beiden Ziffern der Sonderfall überein?

Ich habe auch keine Ahnung, wie Titel diese Frage, wenn jemand aushelfen will ...

EDIT: Ich hatte die Werte für Mastercard und VISA gemischt, so dass nur zu sein richtig :)

+0

Die Antwort lässt fast meine Frage albern aussehen, kann nicht glauben, dass ich diesen nie sah. Vielen Dank. –

Antwort

5

Sie tun können, falls Aussagen wie die folgende:

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

+1 perfekte Antwort. Sollte auch hinzufügen, dass die Reihenfolge der Fallanweisungen wichtig ist; checken Sie nach '37', bevor Sie nach '3' suchen, sonst wird die '3' zuerst ausgelöst –

1

Sie könnten nur die Kartenart Spalte speichern in Tisch und FK auf einen Kartentyp Tisch, oder versuchen, so etwas wie:

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

EDIT
Sie wirklich in Betracht ziehen sollten in einer Tabelle einen Kartentyp Wert zu speichern. Ermitteln Sie es einmalig beim Einfügen und dann können Sie Ihre Daten abfragen, ohne jedes Mal durch diese Ringe springen zu müssen. Sie werden sich auch schützen, wenn der Algorithmus Änderungen an einem bestimmten Punkt, werden alle vorhandenen Daten korrekt

+0

Es wäre offensichtlich eine bessere Lösung, den Kartentyp in der Tabelle zu speichern. Aber wie die meisten von uns bin ich mir sicher, dass Sie mit Legacy-Systemen arbeiten mussten, die alle anderen zu ändern fürchten. Wenn dieser Bericht öfter ausgeführt würde, würde ich härter für die bessere Lösung kämpfen. –

2

Nicht über Ihr System sicher sein, aber in Oracle CASE-Ausdrücke sind genau das, so können Sie nisten sie:

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 
+0

Abgesehen von einem fehlenden 'end' Schlüsselwort aus T-SQL ist das oben Gesagte was ich vorschlagen würde. – MattH

+0

Whoops, hinzugefügt das "Ende" - würde auch in Oracle benötigt werden –

1

Persönlich denke ich, dass Ihre "Longhand" Art elegant ist, weil sie leicht zu lesen und zu pflegen ist, als ich die Antwort @samjudson finden würde (aber ich sehe die Attraktivität ihrer Vorgehensweise). Sie könnten OR verwenden, um mehr als einen Wert pro Fall zu testen. Ich finde LIKE einfacher zu lesen, aber das könnte nur ich sein;) z.

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