2016-05-14 5 views
0

All,SQL Zeile in Zieltabelle auszuwählen, basierend auf Daten, die in mehreren Reihen in Treibertabelle

Siehe unten Datenwerte in zwei Tabellen:

erste Tabelle: oder Treibertabelle enthält Filterkriterien für die IDs der Auswahl aus der zweiten Tabelle

Key1 Value 
1 Banks 
1 Col1|Small 
2 InsuranceCompany 
2 Col2|Global 
3 Banks 
3 Col1|Big 
3 Col2|Local 
4 CreditUnion 

Script

GO 
CREATE TABLE [dbo].[TEST_DRIVER](
    [Key1] [int] NOT NULL, 
    [Value] [varchar](50) NOT NULL 
    ); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('1', 'Banks'); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('1', 'Col1|Small'); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('2', 'InsuranceCompany'); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('2', 'Col2|Global'); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('3', 'Banks'); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('3', 'Col1|Big'); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('3', 'Col2|Local'); 
GO 
INSERT INTO dbo.TEST_DRIVER(Key1, Value) 
VALUES('4', 'CreditUnion'); 
GO 

Hinweis: a) Filterkriterien können in 1, 2 oder 3 Reihen existieren. b) Die ersten Auswahlkriterien werden immer mit der InstitutionsType-Spalte der zweiten Tabelle verknüpft, das zweite und das dritte Kriterium können jedoch nicht existieren und die Spalte, zu der sie hinzugefügt wird, wird in den Daten selbst mit | angegeben Trennsäulen mit Wert

SECOND Tabellenname: IDs aus dieser Tabelle muß in FIRST Tabelle

ID InstitutionType  Col1  Col2 
100 Banks    Small 
200 Banks       Global 
300 Banks    Big   Local 
400 InsuranceCompany Small  Local 
500 InsuranceCompany    Global 
600 CreditUnion   Small  Local 
700 CreditUnion      Global 
800 CDO        Global 

Script

CREATE TABLE [dbo].[TEST_TARGET](
    [ID] [int] NOT NULL, 
    [InstitutionType] [varchar](50) NOT NULL, 
    [Col1] [varchar](50) NULL, 
    [Col2] [varchar](50) NULL 
    ); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('100', 'Banks', 'Small', ''); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('200', 'Banks', '', 'Global'); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('300', 'Banks', 'Big', 'Local'); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('400', 'InsuranceCompany', 'Small', 'Local'); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('500', 'InsuranceCompany', '', 'Global'); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('600', 'CreditUnion', 'Small', 'Local'); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('700', 'CreditUnion', '', 'Global'); 
GO 
INSERT INTO [dbo].[TEST_TARGET](ID, InstitutionType, Col1, Col2) 
VALUES('800', 'CDO', '', 'Global'); 
GO 

ERWARTETES ERGEBNIS basierend auf Filterkriterien gefunden werden:

ID 
100 
300 
500 
600 
700 

Ich kann es mit Cursor/while-Schleife tun, aber ich möchte es mit Abfrage Logik tun. Kann jemand bitte versuchen, dieses interessante Problem zu beantworten?

+0

Meinst du nicht SELECT Logik nicht SET Logik? – Hogan

+0

Sie würden nicht mit so genannten interessanten Problem enden, wenn Sie Ihre Tabellen richtig entwerfen würden ... –

+1

Hallo James, ich stimme mit Ihrem Punkt, aber es gibt Zeiten, wenn Ihre Hände gebunden sind, wenn Sie Daten von externen Systemen und Daten in externe Systeme pushen. – Nilesh

Antwort

0

Der folgende Code wird funktionieren und die genauen Ergebnisse als Ihre Beispielausgabe produzieren, aber scheint ein bisschen aus, wie Sie die Datensätze übereinstimmen. Sieht so aus, als würden Sie nur auf Value und ignorieren col1 & col2 in der Treibertabelle, wenn sie beide nicht verfügbar sind (weshalb Sie 600 & 700 auswählen), aber nicht, wenn die eine oder andere existieren? Ich würde erwarten, dass, sobald der Fahrer Tisch mit col1 und col2 in das richtige Format umgewandelt wird, würden Sie einfach auf alle Spalten so zu ihm beizutreten:

on t.InstitutionType = d.Value
and coalesce(t.col1,'') = coalesce(d.col1,'')
and coalesce(t.col2,'') = coalesce(d.col2,'')

Wenn Da in Ihrer Beispielausgabe ein Fehler aufgetreten ist, können Sie die Join-Bedingung im folgenden Code aktualisieren.

with test_driver_cte AS 
(select 
Key1, 
max(case when Value not like '%|%' then Value end) Value, 
max(case when Value like '%|%' and col = 'Col1' then value2 end) Col1, 
max(case when Value like '%|%' and col = 'Col2' then value2 end) Col2 
from (
    select 
     key1, 
     Value, 
     case when value like '%|%' 
      then substring(Value, 1, 4) 
     end col, 
     case when value like '%|%' 
      then substring(Value, 6, 10) --change 2nd parameter to length of Value-6 
     end value2     
    from test_driver 
    ) td 
group by key1 
) 

select distinct ID 
from test_target t 
join test_driver_cte d 
on (t.InstitutionType = d.Value and d.col1 is null and d.col2 is null) 
or (t.InstitutionType = d.Value and t.col1 = d.col1) 
or (t.InstitutionType = d.Value and t.col2 = d.col2) 
+0

werfen Sie einen Blick auf, wie ich COALESCE in meiner Antwort verwendet - das ist die gleiche Verbindung mit weniger Logik (und damit schneller.) – Hogan

+0

@Hogan nur Problem, das ich mit sah war, wenn col1 oder col2 Null auf table2 auch Sie sein Ich würde kein Match bekommen. – mo2

+0

Das ist nicht korrekt - lesen Sie den Code sorgfältig. Versuch es. – Hogan

0

Was Sie wirklich wollen, ist eine Tabelle, wie diese

Key1 Value   Col1 Col2 
1 Banks   Small 
2 InsuranceCompany  Global 
3 Banks   Big Local 
4 CreditUnion 

Wenn Sie es nicht auf diese Weise beginnen machen, dann können Sie es wie folgt umwandeln:

SELECT D.Key1, D.Value, SUBSTRING(C1.Value,6) AS Col1, SUBSTRING(C2.Value,6) AS Col2 
FROM DRIVER D 
JOIN DRIVER c1 on D.Key1 = c1.Key1 AND LEFT(c1.Value,5) = 'Col1|' 
JOIN DRIVER c2 on D.Key1 = c2.Key1 AND LEFT(c2.Value,5) = 'Col2|' 
WHERE LEFT(D.Value,3) != 'Col' 

Jetzt Sie kommen nur zu erhalten Ihr Ergebnis:

SELECT ID 
FROM TABLE2 
JOIN (
    SELECT D.Key1, D.Value, SUBSTRING(C1.Value,6) AS Col1, SUBSTRING(C2.Value,6) AS Col2 
    FROM DRIVER D 
    JOIN DRIVER c1 on D.Key1 = c1.Key1 AND LEFT(c1.Value,5) = 'Col1|' 
    JOIN DRIVER c2 on D.Key1 = c2.Key1 AND LEFT(c2.Value,5) = 'Col2|' 
    WHERE LEFT(D.Value,3) != 'Col' 
) x ON TABLE2.InstitutionType = x.Key1 
    AND COALESCE(x.col1,TABLE2.Col1) = TABLE2.Col1 
    AND COALESCE(x.col2,TABLE2.Col2) = TABLE2.Col2 

Sie könnten auch so den Join tun (was mehr oder weniger klar sein könnte, aber es ist der sa ich)

) x ON (x.Key1, COALESCE(x.col1,TABLE2.Col1), COALESCE(x.col2,TABLE2.Col2)) = 
     (TABLE2.InstitutionType, TABLE2.Col1, TABLE2.Col2) 

Ich habe nicht getestet, also könnte ich einen Tippfehler oder eine durch einen auf der Teilzeichenfolge haben.

+0

Hallo Hogan, Danke für deinen Vorschlag. Allerdings erhalte ich die erste Tabelle von der Benutzeroberfläche und habe keine Kontrolle über ihre Struktur. Die zweite Tabelle ist wiederum eine vorhandene DW-Tabelle und kann nicht geändert werden. Ich kann nur Daten basierend auf diesen beiden Tabellen ableiten, nicht die Struktur von beiden ändern. – Nilesh

+0

@Nilesh du sagst Vorschlag, ich sage Lösung. – Hogan

Verwandte Themen