2017-12-28 22 views
0

これはちょっと混乱するかもしれませんが、うまくいけば誰かが私を助けてくれます。何らかの理由で私の心が空白になってしまい、問題をタイプすることが助けになるかもしれません。不足しているレコードを含むT-SQLクエリ

私はいくつかのETLのものをやっていますし、特定のId値でグループ化できるデータがあります。私のデータセットの各レコードはLookupIdの値を持ち、別のテーブルに参加して追加情報を得るために使用します。かなり標準INNER JOINものはここにあります。しかし、私はまた、私のデータセットに欠損値LookupIdを含める必要があります。これは私のINNER JOINLEFT JOINに変換します。これはかなり標準的なものです。

あなたは私が何を探しています何のアイデアを取得するには、以下の次のサンプルスキーマとデータを使用することができます。

-- Create sample schema 
CREATE TABLE ETL_DataSet (
    Id INT NOT NULL, 
    LookupId INT NULL, 
    LookupCode CHAR(1) NULL, 
    LookupDesc NVARCHAR(40) NULL 
); 

CREATE TABLE ETL_LookupTable (
    LookupId INT NOT NULL 
    , LookupCode CHAR(1) NOT NULL 
    , LookupDesc NVARCHAR(40) NOT NULL 
    , CONSTRAINT PK_LookupTable_LookupId PRIMARY KEY CLUSTERED (LookupId) 
); 

-- Insert sampel data 
INSERT INTO ETL_LookupTable (LookupId, LookupCode, LookupDesc) VALUES 
    (1, 'Z', 'Z Description'), 
    (2, 'A', 'A Description'), 
    (3, 'B', 'B Description'), 
    (4, 'C', 'C Description'), 
    (5, 'D', 'D Description'), 
    (6, 'E', 'E Description'), 
    (7, 'X', 'X Description'); 

INSERT INTO ETL_DataSet (Id, LookupId, LookupCode, LookupDesc) VALUES 
    (1, 3, 'B', 'B Description'), 
    (1, 5, 'D', 'D Description'), 
    (1, 3, 'B', 'B Description'), 
    (1, 2, 'A', 'A Description'), 
    (2, 4, 'C', 'C Description'), 
    (2, 6, 'E', 'E Description'), 
    (2, 3, 'B', 'B Description'), 
    (2, 2, 'A', 'A Description'); 

そしてここでは、実行するサンプルスクリプトです:

DECLARE @id INT = 1; //change this to 1 or 2 
;WITH LookupCTE AS 
(
    SELECT d.* 
    FROM ETL_LookupTable l INNER JOIN ETL_DataSet d ON l.LookupId = d.LookupId 
    WHERE d.Id = @id --comment this out to get all data in ETL_DataSet 
) 
SELECT * 
FROM ETL_LookupTable l LEFT JOIN LookupCTE cte ON l.LookupId = cte.LookupId 

最終的な目標は、IDのセットにLookupTable値がない場合でも、各IdのすべてのLookupTable値を含めることです。 @Idを1と2の間で変更すると、これが動作することがわかりますが、CTEのWHERE句をコメントアウトすると、間違ったデータが取得されます。カーソルや他の行単位の技法を使わずにこれをやろうとしているので、誰かが私を正しい方向にアシストしたりポイントしたりすることができれば幸いです。

望ましい結果は次のようになります。

Id   LookupId LookupCode LookupDesc 
----------- ----------- ---------- ---------------------------------------- 
1   2   A   A Description 
1   3   B   B Description 
1   3   B   B Description 
1   NULL  C   C Description 
1   5   D   D Description 
1   NULL  E   E Description 
1   NULL  X   X Description 
1   NULL  Z   Z Description 
2   2   A   A Description 
2   3   B   B Description 
2   4   C   C Description 
2   NULL  D   D Description 
2   6   E   E Description 
2   NULL  X   X Description 
2   NULL  Z   Z Description 
+0

あなたは "期待結果" を提供することができますしてください –

+0

@Used_By_Already Nolan Shangさんの希望する出力をご覧ください。NULL行にはまだ他のデータが添付されていますが、最初の列には欠落しているデータも含まれています。 – fujiiface

+0

*私の期待している結果のために、他の誰かが結果を見て、それはほとんど十分です。*真剣に?あなたは本当の期待された結果であることを示すことを気にすることはできませんか? –

答えて

2

あなたがetl_lookupTable情報をetl_dataset.idの直積をしたいように見えるので、cross joinその製品が動作するはず形成します。

select 
ed.*, el.*, d.* 
from (select distinct id from etl_dataset) ed 
cross join (select distinct LookupId, LookupCode, LookupDesc from ETL_LookupTable) el 
left join etl_dataset d on ed.id = d.id and el.LookupId = d.LookupId 
order by 
ed.id, el.LookupCode 
GO 
 
id | LookupId | LookupCode | LookupDesc | Id | LookupId | LookupCode | LookupDesc 
-: | -------: | :--------- | :------------ | ---: | -------: | :--------- | :------------ 
1 |  2 | A   | A Description | 1 |  2 | A   | A Description 
1 |  3 | B   | B Description | 1 |  3 | B   | B Description 
1 |  3 | B   | B Description | 1 |  3 | B   | B Description 
1 |  4 | C   | C Description | null |  null | null  | null   
1 |  5 | D   | D Description | 1 |  5 | D   | D Description 
1 |  6 | E   | E Description | null |  null | null  | null   
1 |  7 | X   | X Description | null |  null | null  | null   
1 |  1 | Z   | Z Description | null |  null | null  | null   
2 |  2 | A   | A Description | 2 |  2 | A   | A Description 
2 |  3 | B   | B Description | 2 |  3 | B   | B Description 
2 |  4 | C   | C Description | 2 |  4 | C   | C Description 
2 |  5 | D   | D Description | null |  null | null  | null   
2 |  6 | E   | E Description | 2 |  6 | E   | E Description 
2 |  7 | X   | X Description | null |  null | null  | null   
2 |  1 | Z   | Z Description | null |  null | null  | null   

dbfiddle here

+0

ありがとうございます。これは私が探していたものを正確に生成する良い解決策です。私はデカルト製品をもっと抱かなければならないという副作用として。私はいつもそれらを避けていました(彼らを避けるために早期に教えられていました)、一時テーブル/ CTEルートを通過しましたが、これは非常にうまくいきます。 – fujiiface

+0

**クロスジョイン**は、格納されていない行が必要な場合に不可欠なツールです。事故デカルト製品**は回避すべきものです**しかし、明示的な結合構文を使用すると、それらは不可能です(テーブル間のコンマに依存する古い結合構文とは異なり、予期しないデカルト積が作成されることがあります)。 –

0

私はあなたを探している結果は、左テーブルとしてETL_DataSetを設定しなければならないためだと思います。以下のようなもの:

SELECT * FROM ETL_DataSet LEFT JOIN ETL_LookupTable ON ETL_DataSet.LookupId = ETL_LookupTable.LookupId 

参考:https://www.w3schools.com/sql/sql_join_left.asp

注:LEFTは左表 からキーワード返しますすべてのレコードを登録しよう...、右の表の一致がない場合でも。

+0

こんにちはヴァレリア代わりにLEFT JOINを右のジョインにすることができましたし、同じことがあります。 – fujiiface

+0

真。それでは、あなたが望むものを手に入れていないのですか? –

+0

私は単一のデータセットですが、データセット全体ではありません。 Nolan Shangの答えは、私が探している結果が現時点で有望視されています。私はその時点でそれをまだ確認しています。 – fujiiface

1

はこれを試してみてください。

DECLARE @id INT = 2; --//change this to 1 or 2 
;WITH IdList AS(
    SELECT DISTINCT id FROM ETL_DataSet 
), LookupCTE AS 
(
    SELECT IdList.id,d.LookupId, d.LookupCode, d.LookupDesc 
    FROM ETL_LookupTable l INNER JOIN IdList ON 1=1 
    LEFT JOIN ETL_DataSet d ON l.LookupId = d.LookupId AND d.id=IdList.id 
    -- WHERE d.Id = @id --comment this out to get all data in ETL_DataSet 
) 

SELECT * FROM LookupCTE --WHERE [email protected] 
 
1 NULL NULL NULL 
1 2 A A Description 
1 3 B B Description 
1 3 B B Description 
1 NULL NULL NULL 
1 5 D D Description 
1 NULL NULL NULL 
1 NULL NULL NULL 
2 NULL NULL NULL 
2 2 A A Description 
2 3 B B Description 
2 4 C C Description 
2 NULL NULL NULL 
2 6 E E Description 
2 NULL NULL NULL 
2
CREATE TABLE #ETL_DataSet (
    Id INT NOT NULL, 
    LookupId INT NULL, 
    LookupCode CHAR(1) NULL, 
    LookupDesc NVARCHAR(40) NULL 
); 

CREATE TABLE #ETL_LookupTable (
    LookupId INT NOT NULL 
    , LookupCode CHAR(1) NOT NULL 
    , LookupDesc NVARCHAR(40) NOT NULL 
    , CONSTRAINT PK_LookupTable_LookupId PRIMARY KEY CLUSTERED (LookupId) 
); 

-- Insert sampel data 
INSERT INTO #ETL_LookupTable (LookupId, LookupCode, LookupDesc) VALUES 
    (1, 'Z', 'Z Description'), 
    (2, 'A', 'A Description'), 
    (3, 'B', 'B Description'), 
    (4, 'C', 'C Description'), 
    (5, 'D', 'D Description'), 
    (6, 'E', 'E Description'), 
    (7, 'X', 'X Description'); 

INSERT INTO #ETL_DataSet (Id, LookupId, LookupCode, LookupDesc) VALUES 
    (1, 3, 'B', 'B Description'), 
    (1, 5, 'D', 'D Description'), 
    (1, 3, 'B', 'B Description'), 
    (1, 2, 'A', 'A Description'), 
    (2, 4, 'C', 'C Description'), 
    (2, 6, 'E', 'E Description'), 
    (2, 3, 'B', 'B Description'), 
    (2, 2, 'A', 'A Description'); 


select * from #ETL_DataSet 
select * from #ETL_LookupTable 

SELECT E.ID,D.LOOKUPID,E1.LOOKUPCODE,E1.LOOKUPDESC 
FROM(
SELECT DISTINCT ID 
FROM #ETL_DATASET) AS E 
CROSS JOIN (SELECT * FROM #ETL_LOOKUPTABLE) AS E1 
LEFT JOIN #ETL_DATASET D ON D.LOOKUPID = E1.LOOKUPID AND D.ID = E.ID 
ORDER BY E.ID,E1.LOOKUPCODE,E1.LOOKUPDESC 

OUTPUT

+----+----------+------------+---------------+ 
| ID | LOOKUPID | LOOKUPCODE | LOOKUPDESC | 
+----+----------+------------+---------------+ 
| 1 | 2  | A   | A Description | 
| 1 | 3  | B   | B Description | 
| 1 | 3  | B   | B Description | 
| 1 | NULL  | C   | C Description | 
| 1 | 5  | D   | D Description | 
| 1 | NULL  | E   | E Description | 
| 1 | NULL  | X   | X Description | 
| 1 | NULL  | Z   | Z Description | 
| 2 | 2  | A   | A Description | 
| 2 | 3  | B   | B Description | 
| 2 | 4  | C   | C Description | 
| 2 | NULL  | D   | D Description | 
| 2 | 6  | E   | E Description | 
| 2 | NULL  | X   | X Description | 
| 2 | NULL  | Z   | Z Description | 
+----+----------+------------+---------------+ 
+0

提供された回答ありがとうございましたが、Used_By_既にあなたにそれを打つ。特定の列名を使用して目的の出力を提供したために上書きされました。 – fujiiface

関連する問題