我正在尝试计算我所有帐户的余额。一个帐户可以与许多交易相关。交易关联到两个帐户。一个帐户是将在transaction.debitaccountid
中记入借方的帐户。另一个帐户将记入transaction.creditaccountid
。
一个事务可以由1:许多TransactionLines组成。这样一来,就可以在不同的类别或预算之间划分交易。
所以我的结构:
(我完全控制了结构,因此可以更改)
我正在尝试获取所有帐户及其余额的列表。稍后我将在linq(ef内核)中进行此操作。但是就目前而言,只是试图找到最有效的方法。
我陷入了两个查询的联合,我认为这不好。
;WITH cte AS (
Select a.ExternalId AS ExternalId, a.Name, SUM(tl.Amount) AS Amount, 1 AS Credit
FROM Account a
INNER JOIN [Transaction] t
ON t.CreditAccountId = a.Id
INNER JOIN TransactionLine tl
ON tl.TransactionId = t.id
WHERE a.AccountTypeId = 1
GROUP BY a.Id, a.ExternalId, a.Name
UNION
Select a.ExternalId AS ExternalId, a.Name, SUM(tl.Amount) AS Amount, -1 AS Credit
FROM Account a
INNER JOIN [Transaction] t
ON t.DebitAccountId = a.Id
INNER JOIN TransactionLine tl
ON tl.TransactionId = t.id
WHERE a.AccountTypeId = 1
GROUP BY a.Id, a.ExternalId, a.Name
)
SELECT ExternalId, Name, SUM(Amount * Credit) FROM cte
GROUP BY ExternalId, Name
我得到正确的答案,但这似乎效率不高。另外,我需要在链接中执行此操作,因此将是来自应用程序的两个查询,然后是在linq中处理的结果。
是否可以在单个SQL查询中执行此操作?也许用OR加入交易?但是然后,不确定是借项还是贷项价值。
也许我需要将金额存储在交易表中?但这可能会出错。可能会更容易并且可以变得安全吗?
编辑: 这几乎可行。但我不能正确分组:
Select a.ExternalId AS ExternalId, a.Name,
SUM(tl.Amount) *
case when t.CreditAccountId = a.Id then 1
when t.DebitAccountId = a.Id then -1 end
as Amt
FROM Account a
INNER JOIN [Transaction] t
ON (t.CreditAccountId = a.Id OR t.DebitAccountId = a.Id )
INNER JOIN TransactionLine tl
ON tl.TransactionId = t.id
WHERE a.AccountTypeId = 1
GROUP BY a.Id, a.ExternalId, a.Name, t.CreditAccountId, t.DebitAccountId
需要将这些按“外部ID”和“名称”分组,并加上“金额”。
编辑2: 固定它。
Select a.ExternalId AS ExternalId, a.Name,
SUM(tl.Amount *
case when t.CreditAccountId = a.Id then 1
when t.DebitAccountId = a.Id then -1 end)
as Amt
FROM Account a
INNER JOIN [Transaction] t
ON (t.CreditAccountId = a.Id OR t.DebitAccountId = a.Id )
INNER JOIN TransactionLine tl
ON tl.TransactionId = t.id
WHERE a.AccountTypeId = 1
GROUP BY a.Id, a.ExternalId, a.Name--, t.CreditAccountId, t.DebitAccountId
结果:
答案 0 :(得分:1)
希望我能正确理解您的问题。
我认为您可以使用OR
和CASE
语句在同一查询中获得结果。请检查以下查询是否有帮助。
Select a.ExternalId AS ExternalId, a.Name,
SUM(tl.Amount *
case when t.CreditAccountId = a.Id then 1
when t.DebitAccountId = a.Id then -1 end)
as Amt
FROM Account a
INNER JOIN [Transaction] t
ON (t.CreditAccountId = a.Id OR t.DebitAccountId = a.Id )
INNER JOIN TransactionLine tl
ON tl.TransactionId = t.id
WHERE a.AccountTypeId = 1
GROUP BY a.Id, a.ExternalId, a.Name