3

以下の表があるとします

ここに画像の説明を入力

CREATE TABLE [dbo].[TestData](
    [ID] [bigint] NOT NULL,
    [InstanceID] [int] NOT NULL,
    [Field] [int] NULL,
    [UserID] [bigint] NOT NULL
) ON [PRIMARY]

GO
INSERT [dbo].[TestData] ([ID], [InstanceID], [Field], [UserID]) 
VALUES (1, 1, NULL, 1000),(2, 1, NULL, 1002),(3, 1, NULL, 1000),
    (4, 1, NULL, 1003),(5, 2, NULL, 1002), (6, 2, NULL, 1005),
    (7, 2, NULL, 1006),(8, 2, NULL, 1007),(9, 3, NULL, 1002),
    (10, 3, NULL, 1006),(11, 3, NULL, 1009),(12, 3, NULL, 1010),
    (13, 1, NULL, 1006),(14, 2, NULL, 1002),(15, 3, NULL, 1003)
GO

UserIDを使用して 2 つのインスタンス間で交差するデータの完全な行を取得するクエリを作成するベスト プラクティスを検索します。

たとえば、InstanceID 1 と 2 の間で交差するUserIDは ( 1002 、 1006 ) であり、結果を取得するために、次のように 2 つの異なる方法でクエリを引用しました。

Select * From TestData
Where UserID in 
( 
    Select T1.UserID From TestData T1 Where InstanceID = 1
        Intersect
    Select T2.UserID From TestData T2 Where InstanceID = 2
)
and InstanceID in (1,2) Order By 1

2番

Select * From TestData
Where UserID in 
( 
    Select Distinct T1.UserID 
    From TestData T1 join TestData T2 on T1.UserID = T2.UserID
    Where T1.InstanceID = 1 and T2.InstanceID = 2
)
and InstanceID in (1,2) Order By 1

したがって、結果は次のようになります

ここに画像の説明を入力

上記のクエリの 1 つは、結果を取得するための最良の方法ですか??

4

4 に答える 4

0

このスクリプトは、Index seek の 2 回の操作と Distinct sorting の 1 回の操作で使用されます。

SELECT ID, InstanceID, Field, UserID
FROM [dbo].[TestData] t
WHERE InstanceID IN(1, 2) 
  AND EXISTS (
              SELECT 1
              FROM [dbo].[TestData] t2
              WHERE InstanceID IN(1, 2) AND t.UserID = t2.UserID
              HAVING COUNT(DISTINCT t2.InstanceID) = 2
              )
ORDER BY t.ID

また

;WITH cte AS
 (
  SELECT ID, InstanceID, Field, UserId
         ,COUNT(*) OVER(PARTITION BY InstanceID, UserID) AS cntInstanceUser
  FROM [dbo].[TestData] t
  WHERE InstanceID IN(1, 2)
  )
  SELECT c.ID, c.InstanceID, c.Field, c.UserID
  FROM cte c
  WHERE EXISTS (
                SELECT 1
                FROM cte c2 
                WHERE c2.UserId = c.UserID
                HAVING COUNT(*) != c.cntInstanceUser
                )
  ORDER BY c.ID

パフォーマンスを改善するには、次のインデックスを使用します。

CREATE INDEX x ON [dbo].[TestData](InstanceID, UserID) INCLUDE(Id, Field)

SQLFiddle のデモ

于 2013-04-23T09:18:08.633 に答える
0

を使用するEXISTSよりも使用する方がよいININサブクエリを使用すると、結果セット全体が処理されます。のEXISTS場合、一致するものが見つかった時点で検索します。あなたの質問に関する限り、INTERSECT実装は単に結合を行うだけなので、違いはないはずです。

編集: 投稿ここでは、INvsEXISTSの場合、オプティマイザーはそれらも同じように扱うと述べています (2008 年現在)。したがって、私の推測と、今読んだことのほとんどは、次のようになります。オプティマイザーが知っているため、それらは同じように実行されます。

于 2013-04-22T23:28:32.273 に答える