У меня есть две таблицы в моей базе данных
Clipboard иClipboardItemMappingКаждый буфер обмена может состоять из одного или нескольких элементов.
В ClipboardItemMapping у меня есть столбец ClipboardId, который является внешним ключом, который ссылается на таблицу Clipboard.
Теперь я хочу, чтобы все эти буферы обмена были одинаковыми, то есть чтобы буферы обмена были одинаковыми, они должны состоять из одинакового количества элементов и одинаковых элементов, имеющих одинаковые itemGuid.
Я написал следующий запрос
INSERT INTO #SharedClipboardsList (ClipboardId, ClipboardGuid, ShareGuid)
SELECT
B.Id,
A.ItemGuid,
A.ShareGuid
FROM
#SharedItems A
INNER JOIN
Clipboard B ON A.ItemGuid = B.Guid
WHERE
ItemType = 7;
-- Calculate the item count for each clipboard in clipboardItemMapping
INSERT INTO #ClipboardItemCounts (ClipboardId, itemCount)
SELECT
A.clipboardId, COUNT(DISTINCT A.itemGuid) AS itemCount
FROM
clipboardItemMapping A
INNER JOIN
#SharedClipboardsList B ON A.clipboardId = B.ClipboardId
WHERE
A.IsDeleted = 0
GROUP BY
A.clipboardId
-- Find combinations of clipboards that have at least one common item
INSERT INTO #ClipboardItemsCombined (Clipboard1Id, Clipboard2Id)
SELECT
A.clipboardId AS Clipboard1Id, B.clipboardId AS Clipboard2Id
FROM
clipboardItemMapping A
INNER JOIN
clipboardItemMapping B ON A.itemGuid = B.itemGuid
AND A.clipboardId <> B.clipboardId
AND A.clipboardId < B.clipboardId
AND A.IsDeleted = 0
AND B.IsDeleted = 0
WHERE
A.clipboardId IN (SELECT ClipboardId FROM #SharedClipboardsList)
AND B.ClipboardId IN (SELECT ClipboardId FROM #SharedClipboardsList)
-- Filter out combinations of clipboards that have the same number of items
INSERT INTO #ClipboardItemsCountMatch (Clipboard1Id, Clipboard2Id)
SELECT
cc1.clipboardId AS Clipboard1Id, cc2.clipboardId AS Clipboard2Id
FROM
#ClipboardItemCounts cc1
INNER JOIN
#ClipboardItemCounts cc2 ON cc1.clipboardId <> cc2.clipboardId
AND cc1.clipboardId < cc2.clipboardId
AND cc1.itemCount = cc2.itemCount;
-- Find combinations of clipboards that have the exact same set of items
INSERT INTO #ClipboardItemsMatch (Clipboard1Id, Clipboard2Id)
SELECT cic.Clipboard1Id, cic.Clipboard2Id
FROM #ClipboardItemsCombined cic
GROUP BY cic.Clipboard1Id, cic.Clipboard2Id
HAVING COUNT(*) = (SELECT itemCount
FROM #ClipboardItemCounts
WHERE clipboardId = cic.Clipboard1Id)
INSERT INTO #DuplicateClipboardsMap (Clipboard1Id, Clipboard2Id)
SELECT DISTINCT
c1.Id AS Clipboard1Id,
c2.Id AS Clipboard2Id
FROM
clipboard c1
INNER JOIN
clipboard c2 ON c1.Id <> c2.Id
AND c1.Id < c2.Id
INNER JOIN
#ClipboardItemsCountMatch cm ON c1.Id = cm.Clipboard1Id
AND c2.Id = cm.Clipboard2Id
INNER JOIN
#ClipboardItemsMatch ci ON c1.Id = ci.Clipboard1Id
AND c2.Id = ci.Clipboard2Id
WHERE
c1.IsDeleted = 0 AND c2.IsDeleted = 0;
SELECT * FROM #DuplicateClipboardsMap
В этом запросе я получаю дубликаты буфера обмена, но не так, как хочу.
Например, если есть одинаковые буферы обмена, идентификаторы которых равны 801 809 815, и другие такие же буферы обмена, идентификаторы которых равны 105 118, то результат, который я хочу, выглядит следующим образом:
|SameClipbords |
|{801,809,815} |
|{105,118} |
Но из запроса, которым я поделился, я получаю этот вывод в комбинации, например:
|Clipboard1 | Clipboard2 |
| 801 | 802 |
| 802 | 809 |
| 801 | 809 |


Вы можете использовать STRING_AGG для объединения элементов, а затем подсчитать, сколько списков у вас есть для каждого набора элементов.
Обязательно используйте детерминированный порядок для агрегации.
SELECT
STRING_AGG(CAST(c.Id AS varchar(20), ',') AS DuplicateClipboards
FROM (
SELECT
c.Id,
STRING_AGG(CAST(cim.itemGuid AS varchar(20), ',') WITHIN GROUP (ORDER BY cim.itemGuid) AS Items
FROM clipboard c
JOIN ClipboardItemMapping cim ON cim.Clipboard1Id = c.Id
WHERE c.IsDeleted = 0
GROUP BY
c.Id
) c
GROUP BY
c.Items
HAVING COUNT(*) > 1;
Да, это сработало после некоторых модификаций .. спасибо!
Пожалуйста, отредактируйте свой вопрос, чтобы предоставить правильные образцы данных и ожидаемые результаты, как указано в информации тега sql