簡體   English   中英

在表中查找重疊的數據集

[英]Find overlapping sets of data in a table

我需要識別重復的數據集,並為那些數據相似的組指定一個組ID。

id     threshold     cost
--     ----------    ----------
1      0             9
1      100           7
1      500           6
2      0             9
2      100           7
2      500           6

我有成千上萬個這樣的集合,大多數是相同的,但具有不同的ID。 我需要找到所有具有相同閾值和成本金額的類似集合,並為其指定一個組ID。 我只是不確定從哪里開始。 最好的方法是迭代每個集合並將其插入到表中,然后每個迭代遍歷表中的每個集合以查找已經存在的內容嗎?

這是您可以嘗試使用關系運算符進行操作的情況之一。 或者,您可以說:“將所有信息放入一個字符串中,並將其用作組ID”。 SQL Server似乎不鼓勵這種方法,但是有可能。 因此,讓我們使用以下特征來表征組:

select d.id,
       (select cast(threshold as varchar(8000)) + '-' + cast(cost as varchar(8000)) + ';'
        from data d2
        where d2.id = d.id
        for xml path ('')
        order by threshold
       ) as groupname
from data d
group by d.id;

哦,我認為可以解決您的問題。 groupname可以作為組ID。 如果您想要一個數字ID(可能是個好主意,請使用dense_rank()

select d.id, dense_rank() over (order by groupname) as groupid
from (select d.id,
             (select cast(threshold as varchar(8000)) + '-' + cast(cost as varchar(8000)) + ';'
              from data d2
              where d2.id = d.id
              for xml path ('')
              order by threshold
             ) as groupname
      from data d
      group by d.id
     ) d;

這是我對問題的解釋的解決方案:

IF OBJECT_ID('tempdb..#tempGrouping') IS NOT NULL DROP Table #tempGrouping;


;
WITH BaseTable AS 
(
              SELECT 1 id, 0 as threshold, 9 as cost

        UNION SELECT 1, 100, 7

        UNION SELECT 1, 500, 6

        UNION SELECT 2, 0, 9

        UNION SELECT 2, 100, 7

        UNION SELECT 2, 500, 6

        UNION SELECT 3, 1, 9

        UNION SELECT 3, 100, 7

        UNION SELECT 3, 500, 6
)

, BaseCTE AS 
(

    SELECT 
        id
        --,dense_rank() over (order by threshold, cost ) as GroupId  
        ,
        (
            SELECT CAST(TblGrouping.threshold AS varchar(8000)) + '/' + CAST(TblGrouping.cost AS varchar(8000)) + ';'
            FROM BaseTable AS TblGrouping 
            WHERE TblGrouping.id = BaseTable.id
            ORDER BY TblGrouping.threshold, TblGrouping.cost
            FOR XML PATH ('')
       ) AS MultiGroup 

    FROM BaseTable 

    GROUP BY id 
) 
,
CTE AS 
(
    SELECT 
         * 
        ,DENSE_RANK() OVER (ORDER BY MultiGroup) AS GroupId  
    FROM BaseCTE 
)
SELECT * 
INTO #tempGrouping
FROM CTE  



-- SELECT * FROM #tempGrouping; 


UPDATE BaseTable 
    SET BaseTable.GroupId = #tempGrouping.GroupId 
FROM BaseTable 

INNER JOIN #tempGrouping 
    ON BaseTable.Id = #tempGrouping.Id 


IF OBJECT_ID('tempdb..#tempGrouping') IS NOT NULL DROP Table #tempGrouping;

其中,BaseTable是您的表,並且您不需要CTE“ BaseTable”,因為您有數據表。
如果閾值和成本字段可以為NULL,則可能需要采取額外的預防措施。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM