2016-05-14 9 views
0

すべての複数の行のデータに基づいて、ターゲットテーブルの行を選択する:SQLは</p> <p>二つのテーブル内のデータ値の下を参照してください、ドライバテーブル

最初の表:またはドライバテーブルにはIDを選択するためのフィルタ基準を含んでいます第二表から

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

スクリプト

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 

注: a)フィルタ基準は、1行、2行または3行に存在する可能性があります。 b)最初の選択基準は、常に2番目のテーブルのInstitutionType列と結合しますが、2番目および3番目の条件が存在する場合と存在しない場合があり、結合する列は|

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 
この表からIDが

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 

FIRST表にフィルタ基準に基づいて発見される必要があるスクリプト

予想される出力:分離カラムは値

SECOND表に名前を付ける

ID 
100 
300 
500 
600 
700 

私はカーソル/ whileループを使ってそれを行うことができますが、私はそれをクエリロジックを使ってやりたいと思います。誰かがこの面白い問題に答えることを試みてもいいですか?

+0

SELECTロジックがSETロジックではないとお考えですか? – Hogan

+0

テーブルを適切に設計すると、面白い問題が起きることはありません。 –

+1

ハイ・ジェームズ、私はあなたの意見に同意しますが、外部システムからデータを取り込む必要があるときに手が縛られることがあります。外部システムにデータをプッシュします。 – Nilesh

答えて

0

以下のコードは、サンプル出力として正確な結果を出力しますが、レコードのマッチング方法は少し違って見えます。あなたは値が一致しているように見え、両方が利用できない場合(つまり、600 & 700を選択している理由)、どちらか一方が存在しない場合、ドライバテーブルのcol1 & col2を無視しているようですか?私は、ドライバテーブルが適切な形式のcol1とcol2で形質転換された後、あなたはこのようなすべての列に、それに参加したいであろうと期待される:

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

場合サンプル出力に間違いがあった場合、以下のコードで結合条件を更新できます。

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

私の答えでCOALESCEをどのように使用したかを見てください - これはロジックが少ない(したがって高速な)同じ結合です。 – Hogan

+0

@Hoganの問題はcol1またはcol2がtable2でnullになるマッチを得られないだろう。 – mo2

+0

これは間違っています - コードをよく読んでください。それを試してみてください。 – Hogan

0

あなたはそれが、あなたはこのようにそれを変換することができ、そのように起動できない場合は何が本当にしたいことは、この

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

のようなテーブルです:

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' 

今、あなただけに参加あなたの結果を入手してください:

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 

あなたはこのような参加をすることもできます(これは多かれ少なかれ明確かもしれませんが、saです私)

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

私はテストしていないので、私は部分文字列にタイプミスやオフオフがあるかもしれません。

+0

こんにちはホーガン、あなたの提案をありがとう。 しかし、私はUIから最初のテーブルを受け取っており、その構造を制御できません。 2番目のテーブルは再び既存のDWテーブルであり、変更することはできません。私はこれらの2つのテーブルに基づいてデータを導き出すことができますが、どちらの構造も変更することはできません。 – Nilesh

+0

@Nileshあなたは提案を言う、私は解決策を言う。 – Hogan

関連する問題