其他示例无法提供适合我情况的解决方案。
假设我有两个表Transactions和Budget。两者都有相同的类别名称,如“抵押贷款”,“保险”,“汽车付款”。但是,预算表每个类别只有1行作为总和,而Transactions表可以有匹配类别的x行。如何生成一个表格,以便我有样本参数@Year = 2016和@Month = 5:
[Category] [Month to Date Transactions Amount] [Month to Date Budget Amount]
Mortgage 1000 1000
Insurance 300 300
Car Payment 600 600
鉴于以下表格:
交易
[Transaction_Date] [Category] [Amount]
20160504 Mortgage 500
20160524 Mortgage 500
20160510 Insurance 300
20160501 Car Payment 200
20160515 Car Payment 200
20160531 Car Payment 200
预算
[Transaction_Date] [Category] [Amount]
20160501 Mortgage 1000
20160501 Insurance 300
20160501 Car Payment 600
在这种情况下,预算表始终使用第一天作为默认值。
当我使用Sum(Case when ...)语句预先形成聚合时,我的查询中的[月末预算金额]似乎是事务表中行数量的一个因子。使用SUM(Case when ...)语句,我尝试将[月份预算金额]列除以COUNT(Case when ...)语句但我收到了“无法执行聚合函数包含聚合或子查询的表达式。“错误?可以这样做吗?我的示例代码如下:
declare @Year as integer = 2016
Declare @Month as integer = 5
SELECT
Transactions.Category
,ISNULL(SUM(CASE WHEN
Year(Transactions.Transaction_Date) = @Year and
Month(Transactions.Transaction_Date) = @Month and
Year(Budget.Transaction_Date) = @Year and
Month(Budget.Transaction_Date) = @Month
THEN Transactions.Amount END),0) AS [Month to Date Transactions Amount]
,ISNULL(SUM(CASE WHEN
Year(Transactions.Transaction_Date) = @Year and
Month(Transactions.Transaction_Date) = @Month and
Year(Budget.Transaction_Date) = @Year and
Month(Budget.Transaction_Date) = @Month
THEN Budget.Amount END),0) AS [Month to Date Budget Amount]
FROM
Transactions
INNER JOIN Category
ON Transactions.Category = Budget.Category
GROUP BY
Transactions.Category
输出
[Category] [Month to Date Transactions Amount] [Month to Date Budget Amount]
Mortgage 1000 2000
Insurance 300 300
Car Payment 600 1800
正如我所观察到的,由于交易中有两个抵押行,我们对预算汇总有双重计算;与汽车付款一样,我们有3行,因此预算汇总是三重计算。
提前感谢所有回复的人。
答案 0 :(得分:0)
这样做的方法不止一种。只需将第二个“SUM”切换为“MAX”,或者,例如,写下这样的内容:
declare @Year as integer = 2016
declare @Month as integer = 5
select t.category, t.amount, b.amount
from
(select category, sum(amount) as amount
from Transactions
where year([Transaction_Date]) = @Year
and month([Transaction_Date]) = @Month
group by category) t
inner join Budget b
on t.category = b.category
and year(b.[Transaction_Date]) = @Year
and month(b.[Transaction_Date]) = @Month
然后添加所需的列名称。
或者,根据您使用变量的确切原因,您可以使用:
select t.year, t.month, t.category, t.amount as transaction_amount, b.amount as budget_amount
from
(select year(Transaction_Date) as year, month(Transaction_Date) as month, category, sum(amount) as amount
from Transactions
group by year(transaction_date), month(transaction_date), category) t
inner join Budget b
on t.year = year(b.transaction_date)
and t.month = month(b.transaction_date)
and t.category = b.category
-- where t.year = @Year and t.month = @Month
order by t.year, t.month, t.category
您当然可以使用where子句限制年份和月份,然后删除年份和月份列以恢复原始要求。
对评论的回应:
select t.category, t.amount as transaction_amount, b.amount as budget_amount
from
(select category, sum(amount) as amount
from Transactions
where year([Transaction_Date]) = @Year
group by category) t
inner join
(select category, sum(amount) as amount
from Budget
where year([Transaction_Date]) = @Year
group by category) b
on t.category = b.category
答案 1 :(得分:0)
在下面的SQL中,请注意当前期间和下一期间的开始日期。此用法是一种标准SARG-able模式,确保在可用时使用索引来优化磁盘访问;并且如果te列类型实际上是日期时间而不是日期,则不会省略或重复计算任何rtansactions。
declare @Year as integer = 2016
, @Month as integer = 5;
declare @thisPdDate as date = datefromParts(@year,@month,1);
declare @nextPdDate as date = dateadd(day,1,eomonth(@thisPdDate));
select t.category, t.amount, b.amount
from (
select category, sum(amount) as amount
from Transactions
where @thisPdDate <= Transaction_Date and Transaction_Date < @nextPdDate
group by category
) t
inner join Budget b
on t.category = b.category
where @thisPdDate <= b.Transaction_Date and b.Transaction_Date < @nextPdDate
这些常见的用法(在WHERE或JOIN子句中)不能SARG 并且需要表扫描:
另外,请注意,使用BETWEEN ... AND ...进行日期查找是一种反模式,除非可以绝对保证列类型将是 date 而不是< EM>日期时间。如果存在任何疑问,请使用上述模式而不是BETWEEN ... AND ....