首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有一种有效的方法来匹配具有相同详细信息集的倍数标头?

是否有一种有效的方法来匹配具有相同详细信息集的倍数标头?
EN

Database Administration用户
提问于 2018-01-09 18:53:26
回答 4查看 120关注 0票数 1

下面是我要问的一个例子:

明细表:

代码语言:javascript
复制
HeaderId | DetailId
    1          100
    1          101
    2          100
    2          101
    3          101
    3          102
    3          103

我正在寻找一种查询策略,它将为我获得所有头ids,并为每个头ids设置相同的详细ids。

所以在这个例子中,我希望HeaderId 1和2连接在一起,因为它们有相同的两条详细记录,但是103不匹配,因为它在集合中有第三项。

到目前为止,我采取的策略是使用STUFF技术创建一个逗号单独的详细值字符串,校验该字符串,然后加入校验和结果。它似乎在工作,但我不知道如何优化它。在一组大约7000头的标题中,它大约在6-7秒内返回.

以下是查询:

代码语言:javascript
复制
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

所以-这是正确的方法吗?如果是的话,我如何优化呢?查询计划对我没有任何影响。最重的是一个桌子的卷轴。而且,如果这有帮助的话,我会尝试把它变成一个函数或proc。

编辑:我开始研究关系划分,我认为这在这里是相关的,但可能与我所想的上下文无关。为了提供更多的上下文,下面是我试图解决的业务案例。

我有一套推广,可以有任何数量的UPC在他们。我正在努力寻找有完全相同的UPC在他们的促销。我看到的许多解决方案都依赖于使用count(*)。所以.只是给任何人看这个的背景。谢谢!

EN

回答 4

Database Administration用户

回答已采纳

发布于 2018-01-16 20:26:01

因此,尼尔·麦克吉根关于关系部门的评论让我转向了这篇文章

我发现“托德的部门-Dwain.C1”的例子是表演性的,并给出了我想要的结果。

这是本文中的示例,除了字段名/表名外,我几乎逐字使用该示例:

代码语言:javascript
复制
-- Todd's Division - Dwain.C 1
SELECT j.ProjectID, s.ResourceID
FROM #ProjectTasks j
JOIN #ResourceTasks s ON j.TaskID = s.TaskID
JOIN
(
    SELECT ProjectID, c_res=COUNT(*)
    FROM #ProjectTasks
    GROUP BY ProjectID
) c ON j.ProjectID = c.ProjectID
GROUP BY j.ProjectID, ResourceID
HAVING COUNT(*) = MAX(c_res)
ORDER BY j.ProjectID, ResourceID;

谢谢你提出的其他建议,他们没能让我完全理解,但最终我找到了解决方案。

票数 2
EN

Database Administration用户

发布于 2018-01-09 20:52:21

下面是一种使用PIVOT和that的方法,如果您有<255个唯一的DetailIDs,就可以工作。在编写完CONCAT函数(2012+)并对其进行压力测试之后,我遇到了一些限制。它运行得很好,在40k行的20k头上<5秒,有254个唯一的详细键和大量匹配。如果你的套装符合这个限制,也许值得一看。

代码语言:javascript
复制
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 < t2.H

您应该能够绕过CONCAT 254的限制,方法是用@d替换select,将枢轴封装到子查询中,并为联接填充另一个@dj。

票数 2
EN

Database Administration用户

发布于 2018-01-10 02:56:41

您可以尝试使用checksum_agg而不是xml连接。

代码语言:javascript
复制
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 < x.copy

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

票数 2
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/195004

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档