【发布时间】:2019-02-23 19:31:27
【问题描述】:
我正在处理一个 T-SQL 查询,以获取过去三周从星期日到星期六的读数总和以及本周的预测值。目标是比较每周的值以得出趋势。
当前周的预测计算是上周日的读数之和 *(一周中的第 7 天)
示例:(27 * (7/4),因为今天星期三是一周的第 4 天。
示例数据如下
+----+---------+-------------+
| ID | Reading | ReadingDate |
+----+---------+-------------+
| 1 | 0 | 9/19/2018 |
| 1 | 27 | 9/18/2018 |
| 1 | 0 | 9/17/2018 |
| 1 | 0 | 9/16/2018 |
| 1 | 0 | 9/15/2018 |
| 1 | 0 | 9/14/2018 |
| 1 | 7 | 9/13/2018 |
| 1 | 12 | 9/12/2018 |
| 1 | 0 | 9/11/2018 |
| 1 | 0 | 9/10/2018 |
| 1 | 17 | 9/9/2018 |
| 1 | 22 | 9/8/2018 |
| 1 | 0 | 9/7/2018 |
| 1 | 0 | 9/6/2018 |
| 1 | 0 | 9/5/2018 |
| 1 | 24 | 9/4/2018 |
| 1 | 0 | 9/3/2018 |
| 1 | 0 | 9/2/2018 |
| 1 | 17 | 9/1/2018 |
| 1 | 0 | 8/31/2018 |
| 1 | 19 | 8/30/2018 |
| 1 | 0 | 8/29/2018 |
| 1 | 0 | 8/28/2018 |
| 1 | 0 | 8/27/2018 |
| 1 | 0 | 8/26/2018 |
+----+---------+-------------+
我希望结果如下。
+----+---------+------+------+------+-----------+-----------+-----------+
| ID | Current | Wk_1 | Wk_2 | wk_3 | Wk1_Trend | Wk2_Trend | Wk3_Trend |
+----+---------+------+------+------+-----------+-----------+-----------+
| 1 | 63 | 36 | 46 | 36 | Up | Down | Up |
+----+---------+------+------+------+-----------+-----------+-----------+
但我得到以下内容。
+----+--------------+-------------+-------------+-------------+-----------+-----------+-----------+-----------------+------------------+-----------------+
| ID | Reading_crnt | Reading_wk1 | Reading_wk2 | Reading_wk3 | Wk1_Trend | Wk2_Trend | Wk3_Trend | Record_Date_wk1 | Record_Date2_wk2 | Record_Date_wk3 |
+----+--------------+-------------+-------------+-------------+-----------+-----------+-----------+-----------------+------------------+-----------------+
| 1 | 47.25 | 27 | 118 | 0 | Up | Down | Up | 9/16/2018 | 8/29/2018 | 8/8/2018 |
+----+--------------+-------------+-------------+-------------+-----------+-----------+-----------+-----------------+------------------+-----------------+
这是创建的脚本,但我看到日期范围不同。请帮我解决这个问题。
WITH
TRTx AS (SELECT (SUM(t1.Reading) * (cast(7 as float)/cast(DATEPART(WEEKDAY,GETDATE()) as float))) Reading_wkexp, t1.ID, CAST(DATEADD(DAY, -1 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), GETDATE()) AS DATE) AS Record_Date
FROM Trend_T t1
WHERE t1.Record_Date BETWEEN CAST(DATEADD(DAY, -1 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), GETDATE()) AS DATE) AND (SELECT max(Record_Date) FROM Trend_T) GROUP BY t1.ID
),
TRT1 AS (SELECT SUM(t1.Reading) Reading_wk1, t1.ID, CAST(DATEADD(DAY, -1 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), GETDATE()) AS DATE) AS Record_Date
FROM Trend_T t1
WHERE t1.Record_Date BETWEEN CAST(DATEADD(DAY, -1 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), GETDATE()) AS DATE) AND (SELECT max(Record_Date) FROM Trend_T) GROUP BY t1.ID
),
TRT2 AS (SELECT SUM(t2.Reading) Reading_wk2, t2.ID, CAST(DATEADD(DAY, -6 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), TRT1.Record_Date) AS DATE) AS Record_Date2
FROM Trend_T t2
JOIN TRT1 ON TRT1.ID = t2.ID
WHERE t2.Record_Date BETWEEN CAST(DATEADD(DAY, -6 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), TRT1.Record_Date) AS DATE) AND TRT1.Record_Date
GROUP BY t2.ID, TRT1.Record_Date
),
TRT3 AS (SELECT SUM(t3.Reading) Reading_wk3, t3.ID, CAST(DATEADD(DAY, -7 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), TRT2.Record_Date2) AS DATE) AS Record_Date3
FROM Trend_T t3
JOIN TRT2 ON TRT2.ID = t3.ID
WHERE t3.Record_Date BETWEEN CAST(DATEADD(DAY, -7 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), TRT2.Record_Date2) AS DATE) AND dateadd(DAY, -1, TRT2.Record_Date2)
GROUP BY t3.ID, TRT2.Record_Date2
)
SELECT TRT1.ID,
Reading_wkexp Reading_crnt,
Reading_wk1,
Reading_wk2,
Reading_wk3,
TRT1.Record_Date AS Record_Date_wk1,
TRT2.Record_Date2 AS Record_Date2_wk2,
TRT3.Record_Date3 AS Record_Date_wk3,
CASE
WHEN Reading_wkexp > Reading_wk1 THEN 'Up'
WHEN Reading_wkexp < Reading_wk1 THEN 'Down'
WHEN Reading_wkexp = Reading_wkexp THEN '-'
END Wk1_Trend,
CASE
WHEN Reading_wk1 > Reading_wk2 THEN 'Up'
WHEN Reading_wk1 < Reading_wk2 THEN 'Down'
WHEN Reading_wk1 = Reading_wk1 THEN '-'
END Wk2_Trend,
CASE
WHEN Reading_wk2 > Reading_wk3 THEN 'Up'
WHEN Reading_wk2 < Reading_wk3 THEN 'Down'
WHEN Reading_wk2 = Reading_wk3 THEN '-'
END Wk3_Trend
FROM TRT1
JOIN TRT2 ON TRT1.ID = TRT2.ID
JOIN TRT3 ON TRT2.ID = TRT3.ID
JOIN TRTx ON TRT1.ID = TRTx.ID
;
下面是创建示例数据的 SQL
CREATE TABLE Trend_T (ID Int, Reading Float null, Record_Date Datetime)
Insert into Trend_T (ID, Reading, Record_Date )
select 1, 0, '2018-09-19' union all
select 1, 27, '2018-09-18' union all
select 1, 0, '2018-09-17' union all
select 1, 0, '2018-09-16' union all
select 1, 0, '2018-09-15' union all
select 1, 0, '2018-09-14' union all
select 1, 7, '2018-09-13' union all
select 1, 12, '2018-09-12' union all
select 1, 0, '2018-09-11' union all
select 1, 0, '2018-09-10' union all
select 1, 17, '2018-09-09' union all
select 1, 22, '2018-09-08' union all
select 1, 0, '2018-09-07' union all
select 1, 0, '2018-09-06' union all
select 1, 0, '2018-09-05' union all
select 1, 24, '2018-09-04' union all
select 1, 0, '2018-09-03' union all
select 1, 0, '2018-09-02' union all
select 1, 17, '2018-09-01' union all
select 1, 0, '2018-08-31' union all
select 1, 19, '2018-08-30' union all
select 1, 0, '2018-08-29' union all
select 1, 0, '2018-08-28' union all
select 1, 0, '2018-08-27' union all
select 1, 0, '2018-08-26' ;
【问题讨论】:
-
你有日历表吗?
-
@gopinath 提示:
( @@DateFirst + DatePart( weekday, SampleDate ) - 1 ) % 7 + 1将始终返回一个从1到7的整数,其中1对应于星期日,而不管DateFirst或Language的设置如何。捕获当前日期,例如declare @Today as Date = GetDate();(注意:as Date,而不是as DateTime。),并且始终使用它可以避免混淆您的意图、一天中的时间或GetDate()返回不同值的情况。 -
@Larnu 是的,但它没有用,因为它只有与年份相关的列。它没有包含工作日编号 n 的列。
-
如果可以减轻我对预期结果的努力,我会很乐意创建我自己的日期表。
标签: sql sql-server tsql azure-sql-database