确定与 T-SQL 中的同一集合连接的项目
Posted
技术标签:
【中文标题】确定与 T-SQL 中的同一集合连接的项目【英文标题】:Determining items that join against the same set in T-SQL 【发布时间】:2009-05-13 02:49:51 【问题描述】:我正在写一份报告,想知道是否有任何方法可以找到加入相同集合的项目?
例如,在下面的查询中,我想查找与同一组产品连接的所有区域:
SELECT Area.Name, AggregateSetOfProductsId
FROM Area
INNER JOIN AreaToProduct ON AreaToProduct.AreaId = Area.Id
GROUP BY Area.Id
我能想到的当前最佳解决方案是编写一个自定义聚合,将 ProductId 唯一标识符散列在一起(例如基于某个字节右移然后将它们异或在一起),但我想我会问是否有更简单的在通过它之前的方式。
【问题讨论】:
“加入反对同一个”是什么意思?是否与相同的产品相关? 【参考方案1】:您可以通过集合操作来做到这一点。在这里,我向您展示如何从 Northwind 获取包含完全相同产品的所有 orderid(这就是您所追求的,对吧?具有完全相同产品的区域)
select distinct o1.orderid
from orders o1 inner join orders o2 on o1.orderid!=o2.orderid
where not exists
(
select * from [order details] od2
where od2.orderId=o2.Orderid
and od2.ProductId NOT IN
(
select productid from [order details] od1
where od1.OrderId=o1.OrderId
)
)
and not exists
(
select * from [order details] od1
where od1.orderId=o1.Orderid
and od1.ProductId NOT IN
(
select productid from [order details] od2
where od2.OrderId=o2.OrderId
)
)
这个想法基本上是这样的:返回订单 o1,其中存在订单 o2,其中没有任何产品不在 o1 的产品列表中,并且没有任何来自 o1 的产品不在产品列表中o2。
【讨论】:
【参考方案2】:您可以使用公用表表达式轻松完成此操作。您将使用 FOR XML PATH 创建一个数组,然后使用该数组来识别匹配的产品。像这样:
;WITH AreaProductSets
AS
(
SELECT a.AreaID, a.Name,
SUBSTRING((SELECT (', ' + CAST(ap.ProductID AS varchar(20)))
FROM AreaToProduct ap
WHERE ap.AreaID = a.AreaID
ORDER BY ap.ProductID
FOR XML PATH ('')), 3, 2000) AS ProductArray
FROM Area AS a
)
SELECT SUBSTRING((SELECT (', ' + CAST(aps2.Name AS varchar(20)))
FROM AreaProductSets aps2
WHERE aps2.ProductArray = aps.ProductArray
ORDER BY aps2.AreaID
FOR XML PATH('')), 3, 2000) AS MatchingAreas,
aps.ProductArray
FROM (SELECT DISTINCT ProductArray FROM AreaProductSets) AS aps
【讨论】:
【参考方案3】:也许使用 EXCEPT 运算符?如果两个集合之间的 EXCEPT 为空,则集合相同。见http://msdn.microsoft.com/en-us/library/ms188055.aspx 此外,要散列结果集,您可以使用内置聚合,如 CHECKSUM_AGG(BINARY_CHECKSUM(*)),请参阅 http://msdn.microsoft.com/en-us/library/ms188920.aspx
【讨论】:
以上是关于确定与 T-SQL 中的同一集合连接的项目的主要内容,如果未能解决你的问题,请参考以下文章
在 T-SQL 中是不是有一个内置命令来确定一个数字是不是在另一个表的范围内