SELECT中聚合值的SQL总和
我有一个带有id和name字段的简单属性表。我还有一个propertyPrices表,其模式和数据如下所示 因此,它指定了给定日期范围的价格。价格值表示该期间内一天的成本 当给定开始和结束日期时,我希望能够根据每个日期范围之间的天数选择价格的总和 我尝试了以下几点:SELECT中聚合值的SQL总和,sql,sql-server,Sql,Sql Server,我有一个带有id和name字段的简单属性表。我还有一个propertyPrices表,其模式和数据如下所示 因此,它指定了给定日期范围的价格。价格值表示该期间内一天的成本 当给定开始和结束日期时,我希望能够根据每个日期范围之间的天数选择价格的总和 我尝试了以下几点: DECLARE @propertyID int = 1; DECLARE @startDate date = '2014/02/13'; DECLARE @endDate date = '2014/02/18'; /* get n
DECLARE @propertyID int = 1;
DECLARE @startDate date = '2014/02/13';
DECLARE @endDate date = '2014/02/18';
/* get number of days between start and end date */
DECLARE @duration int = DATEDIFF(DAY, @startDate, @endDate)
/* select properties with holiday cost */
SELECT
property.name, SUM(dbo.propertyPrices.price) * @duration AS totalCost
FROM
dbo.property INNER JOIN dbo.propertyPrices ON dbo.property.id = dbo.propertyPrices.propertyID
WHERE
property.id = @propertyID
GROUP BY
dbo.property.name
返回2000作为总成本。这是5天,然后乘以400,这是所有价格的总和。我只想为范围内的每一天选择合适的价格。应该如此
100时2天+300时3天=1100
我不确定如何将单个日的值聚合起来。我的首要任务是表现
提前感谢您的帮助
尼克我可以想象编写一个存储过程,或者另一种解决方案是建立一个只包含天数列表的辅助表 如果表calendardate中的所有日期都在受影响的范围内,则可以执行以下操作
SELECT
property.name, SUM(dbo.propertyPrices.price) AS totalCost
FROM
dbo.property
INNER JOIN dbo.propertyPrices
ON dbo.property.id = dbo.propertyPrices.propertyID
JOIN calendar
ON calendar.date between startDate and endDate
WHERE
property.id = @propertyID
GROUP BY
dbo.property.name
我相信您所需要做的就是在原始查询中添加一个case语句,定义您希望应用于日期边界和按开始日期和结束日期分组的条件,这将创建一个表,您可以将该表用作父查询,以按属性名称选择哪些分组 请参阅下面的代码,我使用了表varibales,因此可以轻松地对其进行测试,但您应该能够为自己的表名进行编辑,只需删除@
DECLARE @property AS Table(
id INT
, name NVARCHAR(50)
)
INSERT INTO @property
SELECT 1, 'Property 1' UNION ALL
SELECT 2, 'Property 2'
DECLARE @propertyPrices AS Table(
id INT
, propertyID INT
, startDate datetime
, endDate datetime
, price float
)
INSERT INTO @propertyPrices
SELECT 1, 1, '2014-02-10', '2014-02-15', 100.00 UNION ALL
SELECT 2, 1, '2014-02-16', '2014-02-20', 300.00
DECLARE @propertyID int = 1;
DECLARE @startDate date = '2014/02/13';
DECLARE @endDate date = '2014/02/18';
/* get number of days between start and end date */
DECLARE @duration int = DATEDIFF(DAY, @startDate, @endDate)
/* select properties with holiday cost */
SELECT p.name, SUM(totalCost) FROM (
SELECT
p.name
, CASE
WHEN @startDate > pp.startDate AND @endDate > pp.endDate THEN
SUM(pp.price) * DATEDIFF(DAY, @startDate, @endDate)
WHEN @endDate < pp.endDate THEN
SUM(pp.price) * DATEDIFF(DAY, pp.startDate, @endDate)
ELSE
SUM(pp.price) * DATEDIFF(DAY, pp.startDate, pp.endDate)
END
AS totalCost
FROM
@property p INNER JOIN @propertyPrices pp ON p.id = pp.propertyID
WHERE
p.id = @propertyID
GROUP BY
p.name, pp.startDate, pp.endDate
) p GROUP BY p.name
我会用CTE来做。首先获得具有实际日期范围的价格,然后将价格乘以范围内的天数并求和
with cte as
(
select propertyID, price,
case when startDate < @startDate then @startDate else startDate end as startDate,
case when endDate > @endDate then @endDate else endDate end as endDate
from propertyPrices
where endDate >= @startDate
and startDate <= @endDate
)
, cte2 as
(
select propertyID, sum((datediff(day, startDate, endDate)+1) * price) as totalCost
from cte
group by propertyID
)
select name, totalCost
from cte2
inner join property on id = propertyID
where id = @propertyID
您可以在上查看整个解决方案,我认为通过您传递的参数,它将是2天,而不是3天。您需要为每条记录设置@@startdate和@@enddate的重叠,我将使用案例构造来确定重叠的天数,重叠应乘以每条记录的价格。那个应该有一个总和,这个总和应该除以持续时间。谢谢AshReva,我更新了这个问题。保罗,你能提供一些演示代码吗?我想你的期望值是1200,因为3*10013-15feb+3*30016-18febawesome,谢谢-这就是我想要的那种简单性。我使用了一个表值函数来连接,它工作得很好!感谢您费尽心思创作了这把小提琴。我使用了另一种解决方案,因为我无法在我的上下文中使用CTE。