2016-07-20 3 views
1

Ich habe eine Tabelle, die wie folgt aussehen:TSQL Case-Anweisung

enter image description here

Wie schreibe ich eine Case-Anweisung nur die aktuelle Rate zu ziehen, würde die in diesem Fall Rate14 sein? Immer wenn die Rate 0,0000 ist, müsste ich auf die vorherige Rate zurückfallen.

Jede Hilfe wäre willkommen.

+3

Die Normalisierung des Datenbankschemas wäre ideal. – HardCode

+0

Rechts. Ich bin ein SSRS Report Writer und kann nur verwenden, was zur Verfügung gestellt wird. Versuche es zum Laufen zu bringen. Der SQL-Entwickler kann die Daten nicht normalisieren. -sigh- – BIReportGuy

+1

können Sie erklären, wie das funktioniert? definiere "spätestes" .... jedes Jahr nach dem letzten ist 0? in diesem Fall nach 'Rate14' wäre 0? –

Antwort

7
Select 
    Case When Rate15 > 0 Then Rate15 
     When Rate14 > 0 Then Rate14 
     ... 
     When Rate2 > 0 Then Rate2 
     Else Rate1 
    End Rate 
From Table 
+0

Vereinfachung durch Brute-Force. Manchmal ist dies die beste Antwort. –

+0

Muss ich immer vom letzten Rate-Feld (Rate15) zum frühesten (Rate1) gehen, damit diese Case-Anweisung funktioniert? Es scheint so ... – BIReportGuy

+1

@BIGuy Definitiv, weil ein 'CASE' Ausdruck nach den ersten criterieria austritt, die schlagen. –

3

Stimme völlig mit @Joe C (+1) überein, "rohe Gewalt" ist der einfachste Weg. Nur weil ich die Übung gemacht habe, den Unpivot dafür zu bauen, aus keinem anderen Grund, als die Einfachheit der großen Fallaussage zu rechtfertigen. (Außerdem ist es viel einfacher, mit der „keine Daten“ Situation befassen sich mit dem großen Fall-Anweisung.)

Zunächst gründen einige Daten Beispiel:

--DROP TABLE MyTable 
GO 

CREATE TABLE MyTable 
(
    CUSIPNumber varchar(20) not null 
    ,Year   smallint  not null 
    ,Rate1  float  not null 
    ,Rate2  float  not null 
    ,Rate3  float  not null 
    ,Rate4  float  not null 
    ,Rate5  float  not null 
    ,Rate6  float  not null 
    ,Rate7  float  not null 
    ,Rate8  float  not null 
    ,Rate9  float  not null 
    ,Rate10  float  not null 
    ,Rate11  float  not null 
    ,Rate12  float  not null 
    ,Rate13  float  not null 
    ,Rate14  float  not null 
    ,Rate15  float  not null 
) 

INSERT MyTable values 
    ('001383EA2', 16, 4.0505, 4.0510, 4.0515, 4.0520, 4.0525, 4.0530, 4.0535, 4.0550, 4.0545, 4.0550, 4.0560, 4.0570, 4.0575, 4.0585, 0) 
,('001383EA2', 15, 3.0505, 3.0510, 3.0515, 3.0520, 3.0525, 3.0530, 3.0535, 3.0550, 3.0545, 3.0550, 3.0560, 3.0570, 3.0575, 3.0585, 3.0599) 
,('001383__1', 01, 1.1, 2.2, 3.3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 
,('001383_NoData', 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 

-- What we have 
SELECT * 
from MyTable 

Hier ist die grundlegende Entpivotisierung Aussage. Spalten sind aliased/umbenannt, für max() zu ermöglichen, die neuesten Artikel zu identifizieren (rate2 ist> Rate11 ...)

-- Build the unpivot statement 
SELECT * 
from (select CUSIPNumber, Year, Rate1, Rate3, Rate4, Rate5, Rate6, Rate7, Rate8, Rate9, Rate10, Rate11, Rate12, Rate13, Rate14, Rate15 
     from MyTable) src 
unpivot (RateValue 
      for RateNumber in (Rate1, Rate3, Rate4, Rate5, Rate6, Rate7, Rate8, Rate9, Rate10, Rate11, Rate12, Rate13, Rate14, Rate15) 
     ) unpvt 

-- Whoops! Alias the "Rate" columns, so that they can be sorted 
SELECT * 
from (select 
      CUSIPNumber 
     ,Year 
     ,Rate1 Rate01 
     ,Rate2 Rate02 
     ,Rate3 Rate03 
     ,Rate4 Rate04 
     ,Rate5 Rate05 
     ,Rate6 Rate06 
     ,Rate7 Rate07 
     ,Rate8 Rate08 
     ,Rate9 Rate09 
     ,Rate10 
     ,Rate11 
     ,Rate12 
     ,Rate13 
     ,Rate14 
     ,Rate15 
     from MyTable) src 
unpivot (RateValue 
      for RateNumber in (Rate01, Rate02, Rate03, Rate04, Rate05, Rate06, Rate07, Rate08, Rate09, Rate10, Rate11, Rate12, Rate13, Rate14, Rate15) 
     ) unpvt 

Diese Daten müssen mehrmals referenziert werden. Einfachste Weg, dies zu tun, ist es ein CTE zu machen:

-- Make it a Common Table Expression 
WITH ctePvt 
as (select CUSIPNumber, Year, RateNumber, RateValue 
     from (select 
       CUSIPNumber 
       ,Year 
       ,Rate1 Rate01 
       ,Rate2 Rate02 
       ,Rate3 Rate03 
       ,Rate4 Rate04 
       ,Rate5 Rate05 
       ,Rate6 Rate06 
       ,Rate7 Rate07 
       ,Rate8 Rate08 
       ,Rate9 Rate09 
       ,Rate10 
       ,Rate11 
       ,Rate12 
       ,Rate13 
       ,Rate14 
       ,Rate15 
      from MyTable) src 
     unpivot (RateValue 
       for RateNumber in (Rate01, Rate02, Rate03, Rate04, Rate05, Rate06, Rate07, Rate08, Rate09, Rate10, Rate11, Rate12, Rate13, Rate14, Rate15) 
      ) unpvt) 
select * 
from ctePvt 

Damit können wir die neueste Rate

-- This determines the most recent rate 
WITH ctePvt 
as (select CUSIPNumber, Year, RateNumber, RateValue 
     from (select 
       CUSIPNumber 
       ,Year 
       ,Rate1 Rate01 
       ,Rate2 Rate02 
       ,Rate3 Rate03 
       ,Rate4 Rate04 
       ,Rate5 Rate05 
       ,Rate6 Rate06 
       ,Rate7 Rate07 
       ,Rate8 Rate08 
       ,Rate9 Rate09 
       ,Rate10 
       ,Rate11 
       ,Rate12 
       ,Rate13 
       ,Rate14 
       ,Rate15 
      from MyTable) src 
     unpivot (RateValue 
       for RateNumber in (Rate01, Rate02, Rate03, Rate04, Rate05, Rate06, Rate07, Rate08, Rate09, Rate10, Rate11, Rate12, Rate13, Rate14, Rate15) 
      ) unpvt) 
select 
    CUSIPNumber 
    ,Year 
    ,max(RateNumber) CurrentRate 
    from ctePvt 
    where RateValue <> 0 
group by 
    CUSIPNumber 
    ,Year 

Und damit bestimmen, können wir schließlich den Wert erhalten für die letzten bewerten

-- This gest the values for the most recent rate 
WITH ctePvt 
as (select CUSIPNumber, Year, RateNumber, RateValue 
     from (select 
       CUSIPNumber 
       ,Year 
       ,Rate1 Rate01 
       ,Rate2 Rate02 
       ,Rate3 Rate03 
       ,Rate4 Rate04 
       ,Rate5 Rate05 
       ,Rate6 Rate06 
       ,Rate7 Rate07 
       ,Rate8 Rate08 
       ,Rate9 Rate09 
       ,Rate10 
       ,Rate11 
       ,Rate12 
       ,Rate13 
       ,Rate14 
       ,Rate15 
      from MyTable) src 
     unpivot (RateValue 
       for RateNumber in (Rate01, Rate02, Rate03, Rate04, Rate05, Rate06, Rate07, Rate08, Rate09, Rate10, Rate11, Rate12, Rate13, Rate14, Rate15) 
      ) unpvt) 
select 
    cteBase.CUSIPNumber 
    ,cteBase.Year 
    ,cteBase.RateValue 
    from ctePvt cteBase 
    inner join (-- Most recent rate per item 
       select 
        CUSIPNumber 
       ,Year 
       ,max(RateNumber) CurrentRate 
       from ctePvt 
       where RateValue <> 0 
       group by 
        CUSIPNumber 
       ,Year) cteRecent 
    on cteRecent.CUSIPNumber = cteBase.CUSIPNumber 
    and cteRecent.Year = cteBase.Year 
    and cteRecent.CurrentRate = cteBase.RateNumber 

Beachten Sie, dass dies keine Zeile für die Position zurückkehrt, wo es keine Geschwindigkeitswerte. Es gibt eine Handvoll Wege, die gelöst werden können, aber genug.

Sind Sie nicht froh, dass Sie mit der großen Fallaussage gegangen sind?

3

Ein marginal prägnanter Ansatz ist unten, aber die vollständig erweiterte CASE Version ist wahrscheinlich klarer und effizienter.

Select COALESCE(NULLIF(Rate15,0), 
       NULLIF(Rate14,0), 
       NULLIF(Rate13,0), 
       ... 
       NULLIF(Rate3,0), 
       NULLIF(Rate2,0), 
          Rate1 
       ) AS Rate 
From Table 
+0

Ich dachte auch darüber nach, es wäre besonders praktisch, wenn die Basisdaten eine Null anstelle von 0 hätten –