我有一张颜色表:
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
我只想在第二个表格中出现表Products
(4,5,6)中的idColor
值且Colors
完全具有IdCategory
时从idColor
返回行3个元素具有相同的4, 5, 6
值IdCategory
----------
1
4
。
对于此示例,查询应返回:
{{1}}
答案 0 :(得分: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
Here is a demo让你尝试。
<强>已更新强>
如果要根据表'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)
Here is a fiddle这个例子。
答案 1 :(得分: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不止一次,则必须采用不同的技术。但是从你的例子来看,它看起来并不那样。
答案 2 :(得分:0)
我猜你想根据表中的数据执行这项任务,而不是硬编码值4,5和6(就像给出的一些答案一样)。为此,在my solution中,我创建了一个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
;
查询(see this working in a 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
答案 3 :(得分:-3)
如果我理解你的问题,就应该这样做
select distinct idCategory
from Products
where idColors in (4,5,6)