2016-08-05 6 views
4

Ich muss Daten nehmen, die in einer aktuellen Ansicht vorhanden sind (es wurde abgeflacht) und eine bedingte Logik auf eine Zeile anwenden. Reihenbasis, um seine Darstellung zu ändern. Idealerweise könnten diese Daten von Benutzern in einer Ansicht bewertet werden, auf die von SSMS 2012 zugegriffen wird (fragliche Datenbank ist Microsoft SQL Server 2012). Ich bin kein T-SQL-Guru oder kenne mich mit vielen der neuen Funktionen aus, die SQL Server zu diesem Zweck anbietet. Meine ersten Gedanken waren, einen Cursor und einige Funktionen zu verwenden (ich bin eher ein C# -Entwickler), war mir aber nicht sicher, wie man über eine Ansicht darauf zugreifen könnte (Hauptanforderung). Ich würde es lieber vermeiden, neue Tabellen in der Datenbank zu erstellen (wenn überhaupt möglich).Verwenden Sie T-SQL mit bedingter Logik, um Spaltenwerte für die Verwendung in einer SQL Server-Ansicht zu überschreiben

Unten finden Sie ein Beispiel der aktuellen Daten (As-Is) und wie die Benutzer es anzeigen möchten (To-Be). Die Regeln, die beeinflussen, wie die Daten abgeleitet werden, sind unten aufgeführt.

As-Is (actual source of data): 

PK MainValue Signal1 Signal2 Signal3 Signal4 Signal5 
1 12345  XYZ  12345 NULL NULL NULL  
2 90210  ABC  99999 90210 NULL NULL  
3 970622  XYZ  88888 34652 970622 NULL 


To-Be (how the users would like the data displayed): 

PK MainValue Signal1 Signal2 Signal3 Signal4 Signal5 
1 12345  XYZ  XYZ  XYZ  XYZ  XYZ 
2 90210  ABC  99999 99999 99999 99999 
3 970622  XYZ  88888 34652 34652 34652 

Regeln.

  • prüfen [MainValue] Feld und versuchen, eine Übereinstimmung mit dem ersten [Signal#] Feld zu finden, die wir (immer bei [Signal1] für jede Daten von Startreihe finden
  • Einmal Wir erhalten eine Übereinstimmung, indem wir das vorherige Signalfeld betrachten (zB wenn wir eine Übereinstimmung zwischen [MainValue] und [Signal3] haben, würden wir [Signal2] als unsere tatsächliche Datenquelle verwenden).
  • Nehmen Sie diese Datenquelle und ersetzen Sie nun alle Felder beginnend bei der Stelle, an der die Übereinstimmung gefunden wurde, bis zum letzten Signal [Signal5] -Feld.

Tun Sie dies für jede Zeile. Es sollte nur ein Signalfeld geben, das übereinstimmt und wir werden aufhören zu versuchen, ein Match zu machen, nachdem wir einen Treffer bekommen haben.

+0

Sie haben vergessen, die SQL Sie bisher versucht haben, zu schreiben, damit wir Ihnen dabei helfen können. – sstan

+2

Sie brauchen 'UNPIVOT' Ihren Tisch, machen Sie die Berechnung, dann' PIVOT' wieder –

+1

ich denke, jede Spalte ist 'varchar'? ansonsten kann man 'MainValue' nicht mit' Signal1' vergleichen –

Antwort

4

Sie müssen nullif mit coalesce kombinieren, wie folgt aus:

declare @source table (PK int, MainValue varchar(6), Signal1 varchar(6), Signal2 varchar(6), Signal3 varchar(6), Signal4 varchar(6), Signal5 varchar(6)) 
insert into @source values 
(1, '12345', 'XYZ', '12345', null, null, null), 
(2, '90210', 'ABC', '99999', '90210', null, null), 
(3, '970622', 'XYZ', '88888', '34652', '970622', null) 

select 
    PK, 
    MainValue, 
    nullif(Signal1, MainValue) as Signal1, 
    coalesce(nullif(Signal2, MainValue), nullif(Signal1, MainValue)) as Signal2, 
    coalesce(nullif(Signal3, MainValue), nullif(Signal2, MainValue), nullif(Signal1, MainValue)) as Signal3, 
    coalesce(nullif(Signal4, MainValue), nullif(Signal3, MainValue), nullif(Signal2, MainValue), nullif(Signal1, MainValue)) as Signal4, 
    coalesce(nullif(Signal5, MainValue), nullif(Signal4, MainValue), nullif(Signal3, MainValue), nullif(Signal2, MainValue), nullif(Signal1, MainValue)) as Signal5 
from @source 

Die vorherige Abfrage funktioniert nur, wenn Nullwerte in den übrigen Signale nach dem Spiel sind. Ist dies nicht der Fall ist, werden Sie diese verwenden müssen:

;with cte (PK, MainValue, Signal1 , Signal2, Signal3, Signal4, Signal5) as 
(
    select 
     PK, 
     MainValue, 
     nullif(Signal1, MainValue), 
     case when nullif(Signal1, MainValue) is null then null else nullif(Signal2, MainValue) end, 
     case when nullif(Signal1, MainValue) is null or nullif(Signal2, MainValue) is null then null else nullif(Signal3, MainValue) end, 
     case when nullif(Signal1, MainValue) is null or nullif(Signal2, MainValue) is null or nullif(Signal3, MainValue) is null then null else nullif(Signal4, MainValue) end, 
     case when nullif(Signal1, MainValue) is null or nullif(Signal2, MainValue) is null or nullif(Signal3, MainValue) is null or nullif(Signal4, MainValue) is null then null else nullif(Signal5, MainValue) end 
    from @source 
) 
select 
    PK, 
    MainValue, 
    Signal1, 
    coalesce(Signal2, Signal1) as Signal2, 
    coalesce(Signal3, Signal2, Signal1) as Signal3, 
    coalesce(Signal4, Signal3, Signal2, Signal1) as Signal4, 
    coalesce(Signal5, Signal4, Signal3, Signal2, Signal1) as Signal5  
from cte 
+0

Ich denke, Sie haben es falsch gelesen, das Problem ist nicht 'NULL 'das Problem ist MainValue mit Signal übereinstimmen und propagieren diesen Wert –

+0

Sie können Ihre Abfrage hier testen. http://rextester.com/IZPIA45079 –

+0

@ Aducci - Ich war mir nicht bewusst, die Kraft von COALESCE. Ich hatte eine gepflasterte Verwirrung einer Schleife mit einer Funktion, um zu lokalisieren, wo man beginnt, die anderen Daten zu "überschreiben". Vielen Dank für Ihre Hilfe. Eine kurze Frage für dich. Angenommen, jedes Signalfeld hat ein entsprechendes Beschreibungsfeld (z. B. [Signal1Desc], [Signal2Desc], [Signal3Desc], [Signal4Desc], [Signal5Desc]). Für die Übereinstimmung gelten die gleichen Regeln. Die einzige Falte ist, dass das Beschreibungsfeld auch die Beschreibungswerte in der gleichen Weise überschreiben würde wie das Signalfeld. Hast du irgendwelche Ideen, wie das geht? – user295197

Verwandte Themen