2

色付きのテーブルがあります:

COLORS

idColor   Name
-------   ------
   4      Yellow
   5      Green
   6      Red

そして、データを含む別のテーブルがあります:

PRODUCTS

idProduct   idCategory   idColor
---------   ----------   -------
    1           1           4     
    2           1           5     
    3           1           6     
    4           2           10    
    5           2           11    
    6           2           12    
    7           3           4     
    8           3           5     
    9           3           8     
    10          4           4     
    11          4           5     
    12          4           6     
    13          5           4     
    14          6           4     
    15          6           5     

テーブル(4, 5, 6) の値が 2 番目のテーブルに存在し、同じ値を持つ正確に 3 つの要素があるProducts場合に行を返したいだけです。idColorColorsIdCategoryidColor4, 5, 6

この例では、クエリは次を返す必要があります。

IdCategory
----------
    1      
    4      
4

4 に答える 4

5

これを試して:

SELECT idCategory
FROM PRODUCTS
GROUP BY idCategory
HAVING COUNT(*) = 3
AND COUNT(DISTINCT CASE WHEN idColor IN (4,5,6) THEN idColor END) = 3

これがあなたが試すためのデモです。

更新しました

テーブルの値に応じて結果を動的にフィルタリングする場合`COLOR

SELECT idCategory
FROM PRODUCTS P
LEFT JOIN (SELECT idColor, COUNT(*) OVER() TotalColors
           FROM COLORS) C
     ON P.idColor = C.idColor
GROUP BY idCategory
HAVING COUNT(*) = MIN(C.TotalColors)
AND COUNT(DISTINCT C.idColor) = MIN(C.TotalColors)

これがこの例のフィドルです。

于 2013-02-26T20:20:55.547 に答える
3

集約を使用して、3 つの色すべてが含まれていることを確認し、他の色が含まれていないことを確認できます。このようなもの:

SELECT *
FROM
(
SELECT idCategory
  , SUM(CASE WHEN idColor IN (4, 5, 6) THEN 1 ELSE 0 END) AS GoodColors
  , SUM(CASE WHEN idColor NOT IN (4, 5, 6) THEN 1 ELSE 0 END) AS BadColors
FROM Products
GROUP BY idCategory
) t0
WHERE GoodColors = 3 AND BadColors = 0

idCategory ごとに 4、5、6 が複数回見つかった場合は、別の手法を使用する必要があることに注意してください。しかし、あなたの例からは、そのようには見えません。

于 2013-02-26T20:18:07.873 に答える
0

値4、5、および6をハードコーディングするのではなく(与えられた回答の一部のように)、テーブル内のデータに基づいてこのタスクを実行したいと思います。そのために、私のソリューションdbo.ColorSetsでは、必要な数の異なる色のセットを入力できるテーブルを作成し、クエリを実行して、それらの色のセットに一致するすべての製品カテゴリを確認しました。私があなたのテーブルを使用しなかった理由dbo.Colorは、それが色の名前を備えたルックアップテーブルのように見えたため、可能なリスト全体ではなく、特定の色のセットを選択するのに適切なテーブルではなかったためです。 。

集計を排他的に使用する他のクエリメソッドと比較して、大量のデータでも良好なパフォーマンスを維持する手法を使用しました。どの方法を使用する場合でもProducts、すべての行を比較せずにすべての行を比較することはできないため、このタスクではほとんどの場合、テーブル全体をスキャンする必要があります。ただし、JOINはインデックス可能な列にあり、適切に一致する可能性が非常に高い候補者のみを対象としているため、必要な作業量が大幅に削減されます。

テーブルは次のようになりColorSetsます。

CREATE TABLE dbo.ColorSets (
   idSet int NOT NULL,
   idColor int NOT NULL,
   CONSTRAINT PK_ColorSet PRIMARY KEY CLUSTERED (idSet, idColor)
);

INSERT dbo.ColorSets
VALUES
   (1, 4), 
   (1, 5),
   (1, 6), -- your color set: yellow, green, and red
   (2, 4),
   (2, 5),
   (2, 8)  -- an additional color set: yellow, green, and purple
;

そしてクエリ(これがSqlFiddleで機能することを参照してください):

WITH Sets AS (
   SELECT
      idSet,
      Grp = Checksum_Agg(idColor)
   FROM
      dbo.ColorSets
   GROUP BY
      idSet
), Categories AS (
   SELECT
      idCategory,
      Grp = Checksum_Agg(idColor)
   FROM
      dbo.Products
   GROUP BY
      idCategory
)
SELECT
   S.idSet,
   C.idCategory
FROM
   Sets S
   INNER JOIN Categories C
      ON S.Grp = C.Grp
WHERE
   NOT EXISTS (
      SELECT *
      FROM
         (
            SELECT *
            FROM dbo.ColorSets CS
            WHERE CS.idSet = S.idSet
         ) CS
         FULL JOIN (
            SELECT *
            FROM dbo.Products P
            WHERE P.idCategory = C.idCategory
         ) P
            ON CS.idColor = P.idColor 
      WHERE
          CS.idColor IS NULL
          OR P.idColor IS NULL
   )
;

結果:

idSet  idCategory
 1       1
 2       3
 1       4
于 2013-02-26T21:53:58.527 に答える
-3

私があなたの質問を理解していれば、これでうまくいくはずです

select distinct idCategory
  from Products 
 where idColors in (4,5,6)
于 2013-02-26T20:15:53.553 に答える