Ho una relazione molti-a-molti tra fatture e transazioni con carta di credito, che sto cercando di mappare somme di insieme. Il modo migliore per pensare al problema è immaginare TransactionInvoiceMap come un grafico bipartito. Per ogni sottografo collegato, trova il totale di tutte le fatture e il totale di tutte le transazioni all'interno di quel sottografo. Nella mia query, voglio restituire i valori calcolati per ciascuno di questi sottografi insieme agli ID delle transazioni a cui sono associati. I totali per le transazioni correlate dovrebbero essere identici.Come creare in modo efficiente sottoinsiemi logici di dati in una tabella di mappatura molti-a-molti?
Più esplicitamente, date le seguenti transazioni/fatture
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
la mia uscita desiderata è
TransactionID TotalAsscTransactions TotalAsscInvoiced
1 $100 $100
2 $150 $150
3 $150 $150
Nota che le fatture 2 e 3 e le operazioni 2 e 3 sono parte di un gruppo logico.
Ecco una soluzione (semplificata, i nomi modificati) che funziona apparentemente, ma è molto lenta. Sto avendo difficoltà a capire come ottimizzare questo, ma penso che comporterebbe l'eliminazione delle subquery in TransactionInvoiceGrouping. Sentiti libero di suggerire qualcosa di radicalmente diverso.
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
Sono raggruppati perché tutti si "toccano" a vicenda. Se disegnassi delle linee per ogni relazione, ci sarebbe un grafico che copre i quattro oggetti. Pensavo che esistesse un nome di math per questo tipo di raggruppamento, ma non riesco a ricordarlo. –
@StuartBranhan - Quindi sono raggruppati perché hanno una fattura comune ?, è così che funziona ?. Ed è solo per questo motivo che stai facendo $ 150 come somma totale delle transazioni, perché stai aggiungendo l'importo dalla transazione 2 e dalla transazione 3? – Lamak
Sì, o se c'è una transazione comune. La metafora del grafico funziona meglio per spiegarlo. Hai scritto il commento precedente a cui ho risposto? Probabilmente è una buona idea mantenere i commenti in modo che finiscano per avere un senso per i lettori successivi. –