这个非常棘手......
Products
表格 - >产品有多种颜色..
我想要一个带有某些颜色的产品的存储过程..
例如,圣诞老人帽会有“绿色”和“红色”..我希望所有产品都有“绿色”和“红色”..不仅仅是“绿色”或“红色”,而是两个......
这就是我到目前为止......
问题
代码:
DECLARE @COLORS VARCHAR(MAX) = 'Red, Green'
SELECT *
FROM Products p
LEFT JOIN Product_Colors_Bridge b ON b.ProductID = p.ProductID
LEFT JOIN Product_Colors c on c.ID = b.ColorID
CROSS JOIN dbo.SplitString(@COLORS, ',', NULL)
WHERE CHARINDEX(token, Color) <> 0
答案 0 :(得分:0)
这是set-within-sets子查询的示例。我喜欢用聚合来解决这些问题。这里的代码有点棘手,因为你在字符串中列出了颜色。
select pcp.ProductId, p.ProductName
from Product p join
Product_Colors_Bridge pcb
on p.id = pcb.ProductId join
Product_Colors pc
on pcb.ColorId = pc.Id
group by pcp.ProductId, p.ProductName
having count(distinct (case when charindex(pc.Color, @Colors) > 1 then pc.Color end)) =
(1 + len(@Colors) - len(replace(@Colors, ',', '')))
关键是having
子句。第一部分计算产品在列表中的颜色数。第二个计算颜色的总数,通过使用不带逗号的字符串长度的差异来计算。
如果您愿意,也可以在case
之前移动group by
条件 - 假设您不关心其他颜色。
select pcp.ProductId, p.ProductName
from Product p join
Product_Colors_Bridge pcb
on p.id = pcb.ProductId join
Product_Colors pc
on pcb.ColorId = pc.Id join
dbo.SplitString(@COLORS, ',', NULL) ssc
on ssc.token = pc.Color
group by pcp.ProductId, p.ProductName
having count(*) =
(1 + len(@Colors) - len(replace(@Colors, ',', '')))
答案 1 :(得分:0)
假设您使用的是SQL-Server 2008或更高版本,我建议不要在SQL中使用分隔字符串。如果要将多个值作为参数传递,请使用Table-valued parameters。
所以你首先要让你的类型存储多种颜色(给定一个通用名称,以便可以重复使用):
CREATE TYPE dbo.StringList AS TABLE (Value NVARCHAR(MAX));
这不应该是创建参数的更多努力,但是避免了昂贵的(程序性)拆分方法,您的查询就会变成:
DECLARE @Colors dbo.StringList;
INSERT @Colors VALUES ('Red'), ('Green');
SELECT p.ProductID, p.ProductName
FROM Products p
INNER JOIN Product_Colors_Bridge b
ON b.ProductID = p.ProductID
INNER JOIN Product_Colors c
ON c.ID = b.ColorID
INNER JOIN @colors co
ON co.Value = c.Color
GROUP BY p.ProductID, p.ProductName
HAVING COUNT(DISTINCT c.Color) = (SELECT COUNT(DISTINCT Value) FROM @Colors);
-- HAVING IS KEY HERE, STATING THAT THE COUNT OF DIFFERENT COLOURS ASSOCIATED
-- WITH THE PRODUCT IS THE SAME AS THE NUMBER OF DIFFERENT COLOURS PASSED TO
-- THE QUERY IN THE PARAMETER
答案 2 :(得分:0)
以下是使用like
执行此操作的简单方法:
declare @colors varchar(max) = 'Red,Green';
select p.ProductID, p.ProductName
from Products p
join Product_Colors_Bridge b on b.ProductID = p.ProductID
join Product_Colors c on c.ID = b.ColorID
where ',' + @colors + ',' like '%,' + c.Color + ',%'
group by p.ProductID, p.ProductName
having count(*) = len(@colors) - len(replace(@colors, ',', '')) + 1;
/*
ProductID ProductName
----------- --------------
2 Santa Hat
*/
这将使所有产品至少具有搜索字符串中的所有颜色。
请注意,我已经删除了搜索字符串中的空格,并且我正在添加逗号(在查询本身中)以通过搜索“Blue”来消除“BabyBlue”匹配的可能性。我还假设你的表或搜索字符串中没有重复的颜色或颜色分配。
您必须在您的环境中进行测试,以确定此技术是否比使用UDF进行拆分或以不同方式传递参数(XML,table-valued parameters)更快。也就是说,我通常会远离数据库中的分隔字符串(虽然我们没有将它们存储在这里,但这是一个滑坡无处可去),宁可使用TVP或在应用程序中动态创建查询(使用参数,而不是动态SQL)如果可能的话(可以利用索引)。