这演示了如何将问题分解成公用表表达式(CTE)中的步骤。请注意,您可以将最后的select
替换为注释select
之一以查看中间结果。这是测试,调试或理解正在发生的事情的便捷方式。
你所面对的问题之一就是试图仅基于饮水日期总结数据。如果一棵树在一个没有浇水的月份里种植,那么它不会被计算在内。下面的代码分别总结了日期范围内的种植和供水情况,然后将它们组合成单个结果集。
-- Sample data.
declare @Trees as Table (TreeId Int Identity, CityId Int, DatePlanted Date);
declare @Waterings as Table (WateringId Int Identity, TreeId Int, DateWatered Date);
insert into @Trees (CityId, DatePlanted) values
(1, '20160115'), (1, '20160118'),
(1, '20160308'), (1, '20160318'), (1, '20160118'),
(1, '20170105'),
(1, '20170205'),
(1, '20170401'),
(2, '20160113'), (2, '20160130'),
(2, '20170226'), (2, '20170227'), (2, '20170228');
insert into @Waterings (TreeId, DateWatered) values
(1, '20160122'), (1, '20160129'), (1, '20160210'), (1, '20160601'),
(5, '20160120'), (5, '20160127'), (5, '20160215'), (5, '20160301'), (5, '20160515');
select * from @Trees;
select * from @Waterings;
-- Combine the data.
declare @StartDate as Date = '20100101', @EndDate as Date = '20200101';
with
-- Each tree with the year and month it was planted.
TreesPlanted as (
select CityId, TreeId,
DatePart(year, DatePlanted) as YearPlanted,
DatePart(month, DatePlanted) as MonthPlanted
from @Trees
where @StartDate <= DatePlanted and DatePlanted <= @EndDate),
-- Tree plantings summarized by city, year and month.
TreesPlantedSummary as (
select CityId, YearPlanted, MonthPlanted, Count(TreeId) as Trees
from TreesPlanted
group by CityId, YearPlanted, MonthPlanted),
-- Each watering and the year and month it occurred.
TreesWatered as (
select CityId, W.TreeId,
DatePart(year, W.DateWatered) as YearWatered,
DatePart(month, W.DateWatered) as MonthWatered
from @Trees as T left outer join
@Waterings as W on W.TreeId = T.TreeId
where @StartDate <= W.DateWatered and W.DateWatered <= @EndDate),
-- Waterings summarized by city, year and month.
TreesWateredSummary as (
select CityId, YearWatered, MonthWatered,
Count(distinct TreeId) as Trees, Count(TreeId) as Waterings
from TreesWatered
group by CityId, YearWatered, MonthWatered)
-- Combine the plantings and waterings for the specified period.
select Coalesce(TPS.CityId, TWS.CityId) as CityId,
Coalesce(TPS.YearPlanted, TWS.YearWatered) as Year,
Coalesce(TPS.MonthPlanted, TWS.MonthWatered) as Month,
Coalesce(TPS.Trees, 0) as TreesPlanted,
Coalesce(TWS.Trees, 0) as TreesWatered,
Coalesce(TWS.Waterings, 0) as Waterings
from TreesPlantedSummary as TPS full outer join
TreesWateredSummary as TWS on TWS.CityId = TPS.CityId and
TWS.YearWatered = TPS.YearPlanted and TWS.MonthWatered = TPS.MonthPlanted
order by CityId, Year, Month;
-- Alternative queries for testing/debugging/understanding:
-- select * from TreesPlantedSummary order by CityId, YearPlanted, MonthPlanted;
-- select * from TreesWateredSummary order by CityId, YearWatered, MonthWatered;
现在你想要在结果中包含缺失的月份(没有活动),呃?
你有超过12个月的数据吗?有时几个月会重演 – HABO
'Group by t.CityId,Datepart(month,w.DateWatered),Datepart(year,w.DateWatered)''而不是'DATENAME(month,w.DateWatered)' – TriV
@habo - 是的,有很多年数据。这是为什么它是复制的,因为几个月?我如何解决它? – BattlFrog