【发布时间】:2016-04-12 16:51:33
【问题描述】:
我正在尝试对某个日期范围内的某个列求和。更重要的是我希望这是一个 CTE,因为我必须多次使用它作为更大查询的一部分。由于它是 CTE,它必须具有日期列以及 sum 和 ID 列,这意味着我必须按日期和 ID 分组。这将导致我的结果按 ID 和日期分组,给我的不是一个日期范围内的总和,而是一堆总和,每天一个。
为了简单起见,假设我们有:
create table orders (
id int primary key,
itemID int foreign key references items.id,
datePlaced datetime,
salesRep int foreign key references salesReps.id,
price int,
amountShipped int);
现在,我们想要获取给定销售代表在一个财政年度内的总收入,按项目细分。也就是说,忽略会计年度位:
select itemName, sum(price) as totalSales, sum(totalShipped) as totalShipped
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
group by itemName
足够简单。但是,当您添加任何其他内容(甚至是价格)时,查询会吐出比您想要的更多的行。
select itemName, price, sum(price) as totalSales, sum(totalShipped) as totalShipped
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
group by itemName, price
现在,每个组都是(名称,价格)而不仅仅是(名称)。这是一种 sudocode,但在我的数据库中,只是这个更改导致我的结果集从 13 行跳到 32 行。再加上日期范围,你真的有问题:
select itemName, price, sum(price) as totalSales, sum(totalShipped) as totalShipped
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
and orderDate between 150101 and 151231
group by itemName, price
这与上一个示例相同。问题是让它成为 CTE:
with totals as (
select itemName, price, sum(price) as totalSales, sum(totalShipped) as totalShipped, orderDate as startDate, orderDate as endDate
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
and orderDate between startDate and endDate
group by itemName, price, startDate, endDate
)
select totals_2015.itemName as itemName_2015, totals_2015.price as price_2015, ...
totals_2016.itemName as itemName_2016, ...
from (
select * from totals
where startDate = 150101 and endDate = 151231
) totals_2015
join (
select *
from totals
where startDate = 160101 and endDate = 160412
) totals_2016
on totals_2015.itemName = totals_2016.itemName
现在 CTE 中的分组已经很遥远了,不仅仅是添加价格。我曾考虑将价格查询分解为 CTE 中自己的子查询,但我无法避免需要按日期分组以获得日期范围。任何人都可以看到解决这个问题的方法吗?我希望我已经把事情说得够清楚了。这是针对 IBM iSeries 机器运行的。谢谢!
【问题讨论】:
-
你为什么认为
Since it's a CTE, it has to have the date column是真的? -
抱歉,我没有说清楚。与上一个示例一样,CTE 将用于获取多年。通过这种方式,相同的 CTE 可用于获得两年、三年、四年或更长时间,只需为其指定不同的日期即可。这将输出到网站上的表格中,每个 itemName 一行,列数为年,乘以(价格、totalShipped、totalSales)的计数。
-
也许临时表或视图是比 cte 更好的方法。顺便说一句,如果您花时间和精力正确地格式化您的问题,即,将您的代码格式化为代码,您更有可能获得帮助。
-
如果我使用临时表,难道我还没有必须按日期分组的问题吗?如前所述,这个想法是这个“总数”将在单个查询中使用两次或更多次。关于格式,谢谢提醒。现在应该看起来更好了。
-
一个包含日期和财政年度的临时表让我觉得这是一个好方法。
标签: sql function aggregate common-table-expression