Sql-Server

有沒有一種有效的方法來匹配具有相同細節集的多個標題?

  • January 16, 2018

這是我要問的一個例子:

明細表:

HeaderId | DetailId
   1          100
   1          101
   2          100
   2          101
   3          101
   3          102
   3          103

我正在尋找一種查詢策略,該策略將為我提供所有標題 id,每個標題 id 具有相同的一組詳細資訊 id。

因此,在範例中,我希望 HeaderId 1 和 2 連接在一起,因為它們具有相同的兩條詳細記錄,但 103 不匹配,因為它在集合中有第三項。

到目前為止,我採用的策略是使用該STUFF技術創建一個逗號分隔的詳細值字元串,對該字元串進行校驗和,然後加入校驗和結果。它似乎正在工作,但我不確定如何優化它。在一組大約 7000 個標頭中,它會在大約 6-7 秒內返回。

這是查詢:

with Details as 
(   
   select distinct t2.HeaderId, 
   checksum(stuff((
       select
           ',' + convert(varchar(15), t2.DetailId)
       from
           DetailTable t2
       where
           t2.HeaderId = t2.HeaderId
       for xml path('')
   ),1,1,'')) as ChkSum
from
     DetailTable t1
)
select
   *
from
   Details t1
       join Details t2
           on t2.ChkSum = t1.ChkSum
           and t2.HeaderId <> t1.HeaderId -- To avoid matching the same record

那麼 - 這是正確的方法嗎?如果是,我該如何優化?查詢計劃對我沒有任何影響。最大的重量被賦予桌麵線軸。另外,如果有幫助,我正在嘗試使其成為函式或過程。

**編輯:**我開始研究關係劃分,我認為這在這裡是相關的,但可能與我所想的上下文無關。為了提供更多背景資訊,這是我要解決的業務案例。

我有一組促銷活動,其中可以包含任意數量的 UPC。我正在嘗試查找其中包含完全相同的 UPC 集的促銷活動。我看到的很多解決方案都依賴於使用count(*). 所以 - 對於任何看到這個的人來說,這只是一些背景。謝謝!

這是一種使用PIVOTT-SQL 的方法,如果您有 < 255 個 unique 就可以使用DetailIDsCONCAT在寫完東西並對其進行壓力測試後,我遇到了功能限制(2012+)。它執行得非常好,在超過 40k 行的 20k 標題上 <5 秒,具有 254 個唯一的詳細資訊鍵和大量匹配。如果您的套裝可以滿足該限制,則可能值得一看。

DECLARE @sql varchar(MAX)
DECLARE @d varchar(MAX)
SET @d = stuff((
       SELECT ',' + QUOTENAME(DetailId)
       FROM (SELECT DetailId FROM DetailTable GROUP BY DetailId) d
       for xml path('')
   ),1,1,'')
DECLARE @tbl TABLE (H int, D varchar(254))
INSERT INTO @tbl
EXEC(
'SELECT HeaderId,CONCAT('+@d+') Details --'+@d+'
FROM 
(
   SELECT HeaderId, DetailId, 1 o
   FROM DetailTable
) as s
PIVOT
(
   COUNT(o)
   FOR DetailId IN ('+@d+')
) as pvt'
--Possible subquery and JOIN?
)

SELECT t1.H, t2.H H2  --matches
FROM @tbl t1 JOIN @tbl t2 ON t1.D = t2.D AND t1.H &lt; t2.H

您應該能夠繞過CONCAT254 限制,只需將 select 替換為 @d,將 PIVOT 包裝到子查詢中,然後為 JOIN 填充另一個 @dj。

您可以嘗試使用 checksum_agg 而不是 xml 連接。

with c as (
 select
   h = headerid,
   g = checksum_agg(d) 
          over(partition by headerid)
 from detailtable
)

select distinct main, copy
from (
select
   main = min(l.h) over(partition by l.g), 
   copy = l.h
from c as l
) x
where x.main &lt; x.copy

小提琴:http ://sqlfiddle.com/#!6/df56a/16

引用自:https://dba.stackexchange.com/questions/195004