gpt4 book ai didi

sql-server-2008 - 如何在多对多映射表中有效地创建数据的逻辑子集?

转载 作者:行者123 更新时间:2023-12-04 15:46:44 24 4
gpt4 key购买 nike

我有发票和信用卡交易之间的多对多关系,我试图将总和映射在一起。考虑这个问题的最好方法是把 TransactionInvoiceMap 想象成一个二部图。对于每个连接的子图,找出该子图中所有发票的总数和所有交易的总数。在我的查询中,我想返回为每个子图计算的值以及它们关联的事务 ID。关联交易的总额应相同。

更明确地说,鉴于以下交易/发票

Table: TransactionInvoiceMap
TransactionID InvoiceID
1 1
2 2
3 2
3 3

Table: Transactions
TransactionID Amount
1 $100
2 $75
3 $75

Table: Invoices
InvoiceID Amount
1 $100
2 $100
3 $50

我想要的输出是
TransactionID  TotalAsscTransactions TotalAsscInvoiced
1 $100 $100
2 $150 $150
3 $150 $150

请注意,发票 2 和 3 以及交易记录 2 和 3 是逻辑组的一部分。

这是一个显然有效的解决方案(简化,名称已更改),但速度很慢。我很难弄清楚如何优化它,但我认为这将涉及消除 TransactionInvoiceGrouping 中的子查询。随意提出一些完全不同的建议。
with TransactionInvoiceGrouping as (
select
-- Need an identifier for each logical group of transactions/invoices, use
-- one of the transaction ids for this.
m.TransactionID,
m.InvoiceID,
min(m.TransactionID) over (partition by m.InvoiceID) as GroupingID
from TransactionInvoiceMap m
)
select distinct
g.TransactionID,
istat.InvoiceSum as TotalAsscInvoiced,
tstat.TransactionSum as TotalAsscTransactions
from TransactionInvoiceGrouping g
cross apply (
select sum(ii.Amount) as InvoiceSum
from (select distinct InvoiceID, GroupingID from TransactionInvoiceGrouping) ig
inner join Invoices ii on ig.InvoiceID = ii.InvoiceID
where ig.GroupingID = g.GroupingID
) as istat
cross apply (
select sum(it.Amount) as TransactionSum
from (select distinct TransactionID, GroupingID from TransactionInvoiceGrouping) ig
left join Transactions it on ig.TransactionID = it.TransactionID
where ig.GroupingID = g.GroupingID
having sum(it.Amount) > 0
) as tstat

最佳答案

我已经在 recursive CTE 中实现了该解决方案:

;with TranGroup as (
select TransactionID
, InvoiceID as NextInvoice
, TransactionID as RelatedTransaction
, cast(TransactionID as varchar(8000)) as TransactionChain
from TransactionInvoiceMap
union all
select g.TransactionID
, m1.InvoiceID
, m.TransactionID
, g.TransactionChain + ',' + cast(m.TransactionID as varchar(11))
from TranGroup g
join TransactionInvoiceMap m on g.NextInvoice = m.InvoiceID
join TransactionInvoiceMap m1 on m.TransactionID = m1.TransactionID
where ',' + g.TransactionChain + ',' not like '%,' + cast(m.TransactionID as varchar(11)) + ',%'
)
, RelatedTrans as (
select distinct TransactionID, RelatedTransaction
from TranGroup
)
, RelatedInv as (
select distinct TransactionID, NextInvoice as RelatedInvoice
from TranGroup
)
select TransactionID
, (
select sum(Amount)
from Transactions
where TransactionID in (
select RelatedTransaction
from RelatedTrans
where TransactionID = t.TransactionID
)
) as TotalAsscTransactions
, (
select sum(Amount)
from Invoices
where InvoiceID in (
select RelatedInvoice
from RelatedInv
where TransactionID = t.TransactionID
)
) as TotalAsscInvoiced
from Transactions t

可能有一些优化空间(包括我的对象命名!)但我相信我至少有一个正确的解决方案,它将收集所有可能的交易-发票关系以包含在计算中。

我无法在此页面上获得现有解决方案以提供 OP 所需的输出,并且随着我添加更多测试数据,它们变得更丑陋。我不确定 OP 发布的“慢”解决方案是否如所述正确。我很可能误解了这个问题。

附加信息:

我经常看到递归查询在处理大量数据时可能会很慢。也许这可能是另一个 SO 问题的主题。如果是这种情况,在 SQL 端尝试的事情可能是限制范围(添加 where 子句),索引基表,首先将 CTE 选择到临时表中,索引该临时表,考虑更好的停止条件对于 CTE...当然首先要配置文件。

关于sql-server-2008 - 如何在多对多映射表中有效地创建数据的逻辑子集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11476566/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com