web-dev-qa-db-ja.com

2つのCTEに参加した結果が間違っている

私が抱えていた問題を解決するためのクエリを作成するのにいくつかの助けがありました。解決策は、2つのCTEを作成し、それらを結合してクエリすることであるように見えました。

2つのCTEを単一のクエリとして実行すると、各テーブルには必ず期待されるデータが含まれますが、結合によって生成される結果は本来よりも少なくなり、重複し、さらに3つ以上の重複がある行になります。

;WITH CTE1 AS
(
SELECT FContainerHylla.Name, FContainerPlats.HyllId,
FContainerPlats.x, FContainerPlats.y,
    FContainerPlats.enable, FContainerHylla.Type,
ISNULL((SELECT MIN(fcontainer.id) AS id
FROM FContainer
WHERE (PlatsId = FContainerPlats.id)), 0) AS FcId 
FROM FContainerPlats 
INNER JOIN FContainerHylla ON FContainerPlats.HyllId =

    FContainerHylla.Id
WHERE (FContainerHylla.Type IN (1, 6, 10))
    ),

    CTE2 AS 
    (
SELECT FContainer.id AS SubID, produkter.Produktnamn AS Produktnamn
from FContainer 
INNER JOIN Stämplingar ON FContainer.id = Stämplingar.ID 
INNER JOIN Tempo ON Stämplingar.temponr = Tempo.temponr 
INNER JOIN Produkter ON Tempo.produktnr = Produkter.Produktnr
    ) 

    SELECT CTE1.*, CTE2.Produktnamn
    FROM CTE1
    INNER JOIN CTE2 ON CTE2.SubID = CTE1.FcId
    ORDER BY CTE1.HyllId, CTE1.x, CTE1.y

CTE1は、約2600行の長さのテーブルを生成し、それが正しいことを確認しました。 CTE2は約7000レコードの長さで、正確です。列fcontainer.idは一意のキーです。

これらの2つのテーブルを結合すると、間違った結果が得られます。 CTE1からの結果と同様の結果が得られると期待していましたが、フィールドprodukter.produktnamnを追加しましたが、これを実行しましたが、CTE1からの2500の結果の代わりに、重複した約1600行の結果が得られました。

Create Table For Fcontainer and Stämplingar:

CREATE TABLE [dbo].[FContainer] (
[id]              NUMERIC (18) IDENTITY (1, 1) NOT NULL,
[PlatsId]         NUMERIC (18) CONSTRAINT [DF_FPall_InStoreage] DEFAULT
((0)) NOT NULL,
[Halv]            BIT          NOT NULL,
[FlaggId]         SMALLINT     NOT NULL,
[Kragar]          SMALLINT     NOT NULL,
[TmpFifo]         NUMERIC (18) NULL,
[PackTempoTypeNr] SMALLINT     NULL,
[Invent]          VARCHAR (50) NULL,
CONSTRAINT [PK_FPall] PRIMARY KEY CLUSTERED ([id] ASC) WITH (FILLFACTOR = 
90)
);


CREATE TABLE [dbo].[Stämplingar] (
[Stämplingsnr]   NUMERIC (18) IDENTITY (1, 1) NOT NULL,
[temponr]        NUMERIC (18) NULL,
[Tidpunkt]       DATETIME     NULL,
[antal]          NUMERIC (18) NULL,
[anställd]       CHAR (50)    NULL,
[Bokad]          BIT          CONSTRAINT [DF_Stämplingar_Bokad]
DEFAULT ((0)) NOT NULL,
[Skickad]        BIT          CONSTRAINT [DF_Stämplingar_Skickad]
DEFAULT ((0)) NOT NULL,
[Leveransdatum]  DATETIME     NULL,
[Papp]           NUMERIC (18) NULL,
[daglignr]       NUMERIC (18) NULL,
[ID]             NUMERIC (18) NULL,
[Anställningsnr] NUMERIC (18) NULL,
CONSTRAINT [PK_Stämplingar] PRIMARY KEY NONCLUSTERED ([Stämplingsnr] ASC)
WITH (FILLFACTOR = 90)
);

コメントのヘルプから、左結合で行うことは正しい方法の一歩のようです。これで、1600ではなく約3100の結果が得られました。重複を削除できれば、CTE2経由で到達できない製品の製品を取得する方法を理解できます。

一部の関係は、あるテーブルの.idが別のテーブルの.idと同じではない可能性があるため、あまり明確に定義されていないため、少し混乱する可能性があります。 CTE1のクエリは、私が継承して拡張しようとした元のクエリです。

2
Yo444

コメントでの議論が明らかにしたように、fcontainerStämplingarの間には1対多の関係があるため、FContainerは多くの製品に関連している可能性があります。

このクエリを試してください。fcontainerごとに1つの製品のみが選択されます。

欠落しているfcontainerは、INNER結合が原因です。これをLEFT joinに変更すると、どの製品にも関係のないものも含め、すべてのfcontainerが表示されます。

;WITH CTE1 AS
(
    SELECT 
        FContainerHylla.Name, FContainerPlats.HyllId,
        FContainerPlats.x, FContainerPlats.y,
        FContainerPlats.enable, FContainerHylla.Type,
        ISNULL( (SELECT MIN(fcontainer.id) AS id
                 FROM FContainer
                 WHERE (PlatsId = FContainerPlats.id)
                ), 0) AS FcId 
    FROM FContainerPlats 
      INNER JOIN FContainerHylla ON FContainerPlats.HyllId = FContainerHylla.Id
    WHERE (FContainerHylla.Type IN (1, 6, 10))
),

    CTE2 AS 
(
    SELECT 
        FContainer.id AS SubID, MIN(produkter.Produktnamn) AS Produktnamn
    FROM FContainer 
      INNER JOIN Stämplingar ON FContainer.id = Stämplingar.ID 
      INNER JOIN Tempo ON Stämplingar.temponr = Tempo.temponr 
      INNER JOIN Produkter ON Tempo.produktnr = Produkter.Produktnr
    GROUP BY 
         FContainer.id
) 

SELECT CTE1.*, CTE2.Produktnamn
FROM CTE1
  LEFT JOIN CTE2 ON CTE2.SubID = CTE1.FcId
ORDER BY CTE1.HyllId, CTE1.x, CTE1.y ;
2
ypercubeᵀᴹ