Найти повторяющиеся элементы в SQL Server

У меня есть две таблицы в моей базе данных

  1. Clipboard и
  2. 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      |
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
1
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать 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;

Да, это сработало после некоторых модификаций .. спасибо!

Snake_Eyes 07.08.2023 14:49

Другие вопросы по теме