我正在尝试编写一个返回以下内容的查询:
为此,我提出了以下查询。
declare @StartDate DATE = '2016-08-01'
declare @EndDate DATE = '2016-08-31'
declare @BillingCategory INT = 0
select c.Id, c.Name, c.StartingBalance,
(select coalesce(sum(Amount), 0) from Transactions t where t.CustomerId = c.Id and t.[Date] < @StartDate) xDebits,
(select coalesce(sum(Amount), 0) from Transactions t where t.CustomerId = c.Id and t.[Date] >= @StartDate and t.[Data] <= @EndDate) Debits,
(select coalesce(sum(Amount), 0) from Payments p where p.CustomerId = c.Id and p.[Date] < @StartDate) xCredits,
(select coalesce(sum(Amount), 0) from Payments p where p.CustomerId = c.Id and p.[Date] >= @StartDate and p.[Date] <= @EndDate) Credits
from customers c
where c.BillingCategory in (0,1,2,3,4,5)
此查询似乎给出了我想要的结果。我使用了子查询,因为我似乎无法弄清楚如何使用JOIN
来完成同样的事情。但是我有几个问题。
此查询是否在根据我的WHERE
条件对每个客户进行交易之前检索交易和付款数据?如果是这样,那似乎是一大浪费。可以改善吗?
我还想添加一个GROUP BY
,以按BillingCategory
汇总每个付款和交易列。但是,如果将GROUP BY
列限制为聚合函数(如果它们不在SELECT
子句中时,如何在此处添加GROUP BY
子句?
Transactions
和Payments
表都具有Customers
表的外键。
样本数据(不是真实的)
客户:
Id Name BillingCategory
----- ------- ---------------
1 'ABC' 0
2 'DEF' 1
3 'GHI' 0
交易:
Id CustomerId Date Amount
----- ---------- ------------ ------
1 2 '2016-08-01' 124.90
2 2 '2016-08-04' 37.23
3 1 '2016-08-27' 450.02
付款:
Id CustomerId Date Amount
----- ---------- ------------ ------
1 1 '2016-09-01' 50.00
2 1 '2016-09-23' 75.00
3 2 '2016-09-01' 100.00
答案 0 :(得分:2)
您可以在CTE中分别为Wikipedia2Vec.load()
和Transactions
构建和,然后将它们合并在一起:
Payments
答案 1 :(得分:1)
您可以使用子查询来提高效率。每个客户仅对符合所讨论类别条件的客户进行预查询。这些子查询将始终导致每个客户最多1条记录,因此您不会获得笛卡尔结果。获取您的借方和贷方,然后以左联接重新加入您的客户主列表,以防一侧或另一侧(借方/贷方)不存在。
declare @StartDate DATE = '2016-08-01'
declare @EndDate DATE = '2016-08-31'
declare @BillingCategory INT = 0
select
c.ID,
c.Name,
c.StartingBalance,
coalesce( AllDebits.xDebits, 0 ) DebitsPrior,
coalesce( AllDebits.Debits, 0 ) Debits
coalesce( AllCredits.xCredits, 0 ) CreditsPrior,
coalesce( AllCredits.Credits, 0 ) Credits
from
customers c
LEFT JOIN
( select t.CustomerID,
sum( case when t.[Date] < @StartDate then Amount else 0 end ) xDebits,
sum( case when t.[Date] >= @StartDate then Amount else 0 end ) Debits
from
customers c1
JOIN Transactions t
on c1.CustomerID = t.CustomerID
where
c1.BillingCategory in (0,1,2,3,4,5)
group by
t.CustomerID ) AllDebits
on c.CustomerID = AllDebits.CustomerID
LEFT JOIN
( select p.CustomerID,
sum( case when p.[Date] < @StartDate then Amount else 0 end ) xCredits,
sum( case when p.[Date] >= @StartDate then Amount else 0 end ) Credits
from
customers c1
JOIN Payments p
on c1.CustomerID = p.CustomerID
where
c1.BillingCategory in (0,1,2,3,4,5)
group by
p.CustomerID ) AllCredits
on c.CustomerID = AllCredits.CustomerID
where
c.BillingCategory in (0,1,2,3,4,5)
评论添加
关于托马斯的回答,是的,他们很接近。我的版本还将联接添加到特定计费类别的客户表中,这就是原因。我不知道您的数据库大小,多少客户,多少交易。如果您要处理的确会对性能产生很大影响,那么Thomas的版本将查询每个客户和每个交易。我的版本仅根据您限制的帐单类别条件查询合格的客户。
同样,不知道数据大小,如果您要处理10万条记录,则可能没有明显的性能。如果您要处理10万名客户,那就完全不一样了。
@JonathanWood,正确,但是我的版本中每个内部子查询都包含cus