在sql中查找去年同一周的计数
Posted
技术标签:
【中文标题】在sql中查找去年同一周的计数【英文标题】:Find the count for last year same week in sql 【发布时间】:2017-09-22 06:27:21 【问题描述】:我正在使用以下查询根据过去 5-6 周的日期从表中查找计数,如下所示
BEGIN
SET datefirst 1;
DECLARE @BeginDate datetime= '2016-10-10'
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, @BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, @BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
ORDER BY datepart(wk, DateCreated)
END
这将返回如下结果集:
Total WeekNumber WeekStartDate WeekEndDate
51295 36 29.08.2016 04.09.2016
48133 37 05.09.2016 11.09.2016
38991 38 12.09.2016 18.09.2016
38074 39 19.09.2016 25.09.2016
37192 40 26.09.2016 02.10.2016
20835 41 03.10.2016 09.10.2016
23781 42 10.10.2016 16.10.2016
现在我想在最后添加一列,其中包含去年同一周数的计数。
我可以在这个查询中实现同样的效果吗?或者我应该为它写一个完全不同的查询?以及如何进行此查询?
【问题讨论】:
你不能只算上一年并加入 weeknumber 吗?因此,创建 2 个 CTE,一个包含 2016 年的数据,一个包含 2015 年的数据,然后在 weeknumber 中加入这些,然后您可以在同一行获得两年的总数。 最困难的部分是找出与同一周数相对应的上一年日期的确切范围。 2016 年 10 月 10 日是星期一 - 一周的第一天。 2015 年 10 月 10 日是星期六,所以简单的DATEADD(year, -1, ...)
是不够的。我强烈建议使用日历表。
@VladimirBaranov 日期可以忽略。我的情况仅与周数相关
【参考方案1】:
您可以使用UNION
和DATEDIFF
来获得上一年的相同内容:
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, @BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, @BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
UNION ALL
SELECT
count(*) as Total
, datepart(wk, DATEDIFF(year,1,DateCreated )) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, @BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, @BeginDate)
GROUP BY datepart(wk, DATEDIFF(year,1,DateCreated ))
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,6),104)
ORDER BY datepart(wk, DATEDIFF(year,1,DateCreated ))
【讨论】:
【参考方案2】:把你的最终结果放到一个临时表中,然后做这样的事情:
请务必检查您与上一年的日期逻辑。但希望你明白这个逻辑。我没有测试你的“版本”是否如我所写的那样正确,但我希望你能得到图片。
测试版结果
测试版:
DECLARE @Weeks1 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
DECLARE @Weeks2 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
insert into @Weeks1 (Total,Weeknumber,WeekStartDate,Weekenddate)
values ('51295', '36' ,'29.08.2016' ,'04.09.2016'),
('48133', '37' ,'05.09.2016' ,'11.09.2016'),
('38991', '38' ,'12.09.2016' ,'18.09.2016'),
('38074', '39' ,'19.09.2016' ,'25.09.2016'),
('37192', '40' ,'26.09.2016' ,'02.10.2016'),
('20835', '41' ,'03.10.2016' ,'09.10.2016'),
('23781', '42' ,'10.10.2016' ,'16.10.2016')
insert into @Weeks2 (Total,Weeknumber,WeekStartDate,Weekenddate)
values ('324234', '36' ,'29.08.2015' ,'04.09.2015'),
('22333', '37' ,'05.09.2015' ,'11.09.2015'),
('23444', '38' ,'12.09.2015' ,'18.09.2015'),
('566666', '39' ,'19.09.2015' ,'25.09.2015'),
('4345', '40' ,'26.09.2015' ,'02.10.2015'),
('8657', '41' ,'03.10.2015' ,'09.10.2015'),
('8567567', '42' ,'10.10.2015' ,'16.10.2015')
Select a.Total,b.Total as
LastYearTotal,a.Weeknumber,A.WeekStartDate,a.Weekenddate from @Weeks1 a
inner join @Weeks2 b on a.Weeknumber = b.Weeknumber
使用您的版本:
DECLARE @Weeks1 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
DECLARE @Weeks2 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
BEGIN
SET datefirst 1;
DECLARE @BeginDate datetime= '2016-10-10'
insert into @Weeks1 (Total,Weeknumber,WeekStartDate,Weekenddate)
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, @BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, @BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
ORDER BY datepart(wk, DateCreated)
END
BEGIN
SET datefirst 1;
DECLARE @BeginDate2 datetime= '2015-10-10'
insert into @Weeks2 (Total,Weeknumber,WeekStartDate,Weekenddate)
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, @BeginDate2)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, @BeginDate2)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
ORDER BY datepart(wk, DateCreated)
END
Select a.Total,b.Total as
LastYearTotal,a.Weeknumber,A.WeekStartDate,a.Weekenddate from @Weeks1 a
inner join @Weeks2 b on a.Weeknumber = b.Weeknumber
【讨论】:
刚刚将第二个 begindate 变量更改为 begindate2 因为你不能有 2 个同名的变量。否则我认为它会起作用。 从字符串转换日期和/或时间时转换失败。我收到的信息是什么 也许是因为我们不使用相同的日期。将日期更正为您通常的书写方式。并确保表上的数据类型正确。或者将日期列设置为 nvarchar 而不是数据类型 DATE 我可以想象您的 WeekStartDate 和 WeekEndDate 是 nvarchar 或 varchar,因为您有 29.08.2016 - 我认为它不适用于数据类型日期。所以尝试根据列来制作表格字符串。 我将类型改为nvarchar,结果是String,否则二进制数据会被截断。【参考方案3】:如果只有几周很重要,您可以先进行一些日期计算并进行更简单的查询
SET datefirst 1;
DECLARE @BeginDate datetime = '2016-10-10'; -- must be start of the week , <= last week -6
declare @nweeks int = 6;
-- this year interval
declare @b1Date datetime = dateadd(week, -@nweeks , @BeginDate); --inclusive
declare @e1Date datetime = dateadd(week, 1 , @BeginDate); -- exclusive
declare @thisYear int = datepart(year, @b1Date);
-- previous year interval
declare @bwk int = datepart(week, @b1Date);
declare @year2 datetime= dateadd(year,datediff(year,0,@b1Date)-1,0);
declare @b2Date datetime = dateadd(week, @bwk-1, @year2);
declare @e2Date datetime = dateadd(week, @bwk + @nweeks, @year2);
-- check it
select @BeginDate, @b1Date, @e1Date, @bwk, @b2Date, @e2Date, datepart(week, @b2Date);
SELECT
count(case datepart(year, DateCreated) when @thisYear then 1 end) as TotalThisYear
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datepart(week,DateCreated)-@bwk -1,@b1Date),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(day,7*(datepart(week,DateCreated)-@bwk-1)+6,@b1Date),104) as WeekEndDate
, count(case datepart(year, DateCreated) when @thisYear-1 then 1 end) as TotalPrev
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= @b1Date AND CONVERT(date,DateCreated) <@e1Date
OR
CONVERT(date,DateCreated) >= @b2Date AND CONVERT(date,DateCreated) <@e2Date
GROUP BY datepart(wk, DateCreated)
ORDER BY datepart(wk, DateCreated)
【讨论】:
【参考方案4】:是的,您可以使用相同的查询,但只需进行少量修改。我使用了 2 个 CTE,一个用于您的查询,另一个用于前一年的几周。然后在 weeknumber 上加入两者以获取所需的最后一列,如下所示。
BEGIN
SET datefirst 1;
DECLARE @BeginDate datetime= '2016-10-10'
;WITH CTE1 as
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, @BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, @BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
,CTE2 as
SELECT count(*) as Total
,datepart(wk, dateadd(year, -1, DateCreated)) as WeekNumber
FROM TABLESES
GROUP BY datepart(wk, dateadd(year, -1, DateCreated))
SELECT CTE1.*, CTE2.Total
FROM CTE1 JOIN CTE2
ON CTE1.WeekNumber = CTE2.WeekNumber
END
【讨论】:
以上是关于在sql中查找去年同一周的计数的主要内容,如果未能解决你的问题,请参考以下文章