Tengo una relación de muchos a muchos entre las facturas y las transacciones con tarjeta de crédito, y estoy tratando de mapear las sumas de las mismas. La mejor manera de pensar en el problema es imaginar TransactionInvoiceMap como un gráfico bipartito. Para cada subgrafo conectado, encuentre el total de todas las facturas y el total de todas las transacciones dentro de ese subgrafo. En mi consulta, deseo devolver los valores calculados para cada uno de estos subgrafos junto con los identificadores de transacciones a los que están asociados. Los totales para las transacciones relacionadas deben ser idénticos.¿Cómo creo eficientemente subconjuntos lógicos de datos en una tabla de asignación de muchos a muchos?
Más explícitamente, dadas las siguientes operaciones/facturas
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
mi salida deseada es
TransactionID TotalAsscTransactions TotalAsscInvoiced
1 $100 $100
2 $150 $150
3 $150 $150
Nota que las facturas 2 y 3 y las transacciones 2 y 3 son parte de un grupo lógico.
Aquí hay una solución (simplificada, nombres cambiados) que aparentemente funciona, pero es muy lenta. Me está costando entender cómo optimizar esto, pero creo que implicaría eliminar las subconsultas en TransactionInvoiceGrouping. Siéntase libre de sugerir algo radicalmente diferente.
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
Se agrupan porque todos "se tocan" entre sí. Si dibujara líneas para cada relación, habría un gráfico que cubriría los cuatro objetos. Pensé que había un nombre mathy para este tipo de agrupación, pero no puedo recordarlo. –
@StuartBranhan - Entonces, ¿están agrupados porque tienen una factura común ?, ¿es así como funciona? ¿Y solo por esa razón está asumiendo $ 150 como el monto total de las transacciones, porque está agregando el monto de la transacción 2 y la transacción 3? – Lamak
Sí, o si hay una transacción común. La metáfora gráfica funciona mejor para explicarlo. ¿Escribiste el comentario anterior al que respondí? Probablemente sea una buena idea guardar los comentarios para que tengan sentido para los lectores posteriores. –