Определение элементов, которые объединяются с одним и тем же набором в T-SQL - PullRequest
0 голосов
/ 13 мая 2009

Я пишу отчет, и мне было интересно, есть ли способ найти предметы, которые объединяются в идентичные наборы?

Например, в следующем запросе я хочу найти все области, которые объединяются с одним и тем же набором продуктов:

SELECT Area.Name, AggregateSetOfProductsId
FROM Area
INNER JOIN AreaToProduct ON AreaToProduct.AreaId = Area.Id
GROUP BY Area.Id

На сегодняшний день лучшим решением, о котором я мог подумать, было написание собственного агрегата, который хэшировал уникальные идентификаторы ProductId (что-то вроде сдвига вправо на основе некоторого байта, а затем их хорировал вместе), но я решил, что есть вопрос: путь, прежде чем пройти через это.

Ответы [ 3 ]

1 голос
/ 13 мая 2009

Вы можете легко сделать это, используя Common Table Expression. Вы должны использовать 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
1 голос
/ 13 мая 2009

Вы можете сделать это с помощью операций над множествами. Здесь я покажу вам, как получить все ордериды от северного ветра, которые содержат точно такие же продукты (что вам нужно, верно? Области с точно такими же продуктами)

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, отсутствующих в списке продуктов. о2.

0 голосов
/ 13 мая 2009

Возможно, используйте оператор EXCEPT? Если ИСКЛЮЧЕНИЕ между двумя наборами пусто, наборы идентичны. Смотри http://msdn.microsoft.com/en-us/library/ms188055.aspx Также для хэширования набора результатов вы можете использовать встроенные агрегаты, такие как CHECKSUM_AGG (BINARY_CHECKSUM (*)), см. http://msdn.microsoft.com/en-us/library/ms188920.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...