SQL对过去三周的周日至周六之间的值求和

时间:2018-09-19 15:07:26

标签: sql sql-server tsql azure-sql-database

我正在研究一种T-SQL查询,以获取过去三周的周日至周六的读数总和以及当前周的预测值。目标是比较每周的值以显示趋势。

当前周的预测计算是从上一个星期日开始的读数总和*(一周的7 /天)

例如:(27 *(7/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' ;

2 个答案:

答案 0 :(得分:1)

尝试一下,我得到您的预期结果。我基本上将每周的开始日期和结束日期保存到临时表中,然后在编译结果时使用它。

SELECT *
INTO #Weeks
FROM (
SELECT WeekType = 0, StartDate = CONVERT(CHAR(10), DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)), GETDATE()), 101), EndDate = CONVERT(CHAR(10), DATEADD(DAY, 6, DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)), GETDATE())), 101)
UNION ALL
SELECT WeekType = 1, StartDate = CONVERT(CHAR(10), DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)) - 7, GETDATE()), 101), EndDate = CONVERT(CHAR(10), DATEADD(DAY, 6, DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)) - 7, GETDATE())), 101)
UNION ALL
SELECT WeekType = 2, StartDate = CONVERT(CHAR(10), DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)) - 14, GETDATE()), 101), EndDate = CONVERT(CHAR(10), DATEADD(DAY, 6, DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)) - 14, GETDATE())), 101)
UNION ALL
SELECT WeekType = 3, StartDate = CONVERT(CHAR(10), DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)) - 21, GETDATE()), 101), EndDate = CONVERT(CHAR(10), DATEADD(DAY, 6, DATEADD(DAY, (-1) * (DATEPART(WEEKDAY, GETDATE() - 1)) - 21, GETDATE())), 101)
) t
GO
WITH 
TRTx AS (SELECT ((SELECT SUM(t1.Reading) FROM Trend_T t1 WHERE t1.Record_Date BETWEEN (SELECT StartDate FROM #Weeks WHERE WeekType = 1) AND (SELECT EndDate FROM #Weeks WHERE WeekType = 1) AND t1.ID = t0.ID )
         * (cast(7 as float)/cast(DATEPART(WEEKDAY,GETDATE()) as float))) Reading_wkexp, 
         t0.ID 
         FROM Trend_T t0
         WHERE t0.Record_Date BETWEEN (SELECT StartDate FROM #Weeks WHERE WeekType = 0) AND (SELECT EndDate FROM #Weeks WHERE WeekType = 0)  
         GROUP BY t0.ID
         ),
TRT1 AS (SELECT SUM(t1.Reading) Reading_wk1, t1.ID 
         FROM Trend_T t1
         WHERE t1.Record_Date BETWEEN (SELECT StartDate FROM #Weeks WHERE WeekType = 1) AND (SELECT EndDate FROM #Weeks WHERE WeekType = 1) 
         GROUP BY t1.ID
         ),
TRT2 AS (SELECT SUM(t2.Reading) Reading_wk2, t2.ID 
         FROM Trend_T t2 
            JOIN TRT1 ON TRT1.ID = t2.ID
         WHERE t2.Record_Date BETWEEN (SELECT StartDate FROM #Weeks WHERE WeekType = 2) AND (SELECT EndDate FROM #Weeks WHERE WeekType = 2)
         GROUP BY t2.ID 
         ),
TRT3 AS (SELECT SUM(t3.Reading) Reading_wk3, t3.ID 
         FROM Trend_T t3
            JOIN TRT2 ON TRT2.ID = t3.ID
         WHERE t3.Record_Date BETWEEN (SELECT StartDate FROM #Weeks WHERE WeekType = 3) AND (SELECT EndDate FROM #Weeks WHERE WeekType = 3)
         GROUP BY t3.ID 
         )
SELECT TRT1.ID,
       Reading_wkexp Reading_crnt,
       Reading_wk1,
       Reading_wk2,
       Reading_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
GO
DROP TABLE #Weeks

答案 1 :(得分:0)

我复杂了日期范围的计算。给了一些想法,并简化了日期范围以获得我的结果。下面是我的解决方案。

WITH 
TRT AS  (SELECT t.ID, t.Reading, t.RECORD_DATE 
         FROM Trend_T t
         WHERE t.RECORD_DATE = (SELECT max(RECORD_DATE) FROM Trend_T) 
         ),
TRTx AS (SELECT (SUM(tx.Reading)*(cast(7 as float)/cast(DATEPART(WEEKDAY,GETDATE()) as float))) Reading_wkexp, tx.ID, CAST(DATEADD(DAY, -1 * ((DATEPART(WEEKDAY, GETDATE()) % 7) - 1), GETDATE()) AS DATE) AS Record_Date
         FROM Trend_T tx
         WHERE tx.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 tx.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,-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,-7, TRT1.Record_Date) AS DATE) AND CAST(DATEADD(DAY,-1,TRT1.Record_Date)  AS DATE)
         GROUP BY t2.ID, TRT1.Record_Date 
         ),
TRT3 AS (SELECT SUM(t3.Reading) Reading_wk3, t3.ID, CAST(DATEADD(DAY,-8,TRT1.Record_Date) AS DATE) AS Record_Date3
         FROM Trend_T t3
            JOIN TRT1 ON TRT1.ID = t3.ID
         WHERE t3.Record_Date BETWEEN CAST(DATEADD(DAY,-14,TRT1.Record_Date) AS DATE) AND CAST(DATEADD(DAY,-8,TRT1.Record_Date) AS DATE)
         GROUP BY t3.ID, TRT1.Record_Date 
         ),
TRT4 AS (SELECT SUM(t4.Reading) Reading_wk4, t4.ID, CAST(DATEADD(DAY,-15,TRT1.Record_Date) AS DATE) Record_Date4
         FROM Trend_T t4
            JOIN TRT1 ON TRT1.ID = t4.ID
         WHERE t4.Record_Date BETWEEN CAST(DATEADD(DAY,-21,TRT1.Record_Date) AS DATE) AND CAST(DATEADD(DAY,-15,TRT1.Record_Date) AS DATE)
         GROUP BY t4.ID, TRT1.Record_Date 
         )
SELECT TRT1.ID,
       TRT.Reading  AS Reading_crnt,
       Reading_wk1,
       Reading_wkexp,
       Reading_wk2,
       Reading_wk3, 
       Reading_wk4,      
       Cast(Getdate() as Date) AS Record_Date_wk1,
       TRT2.Record_Date2 AS Record_Date2_wk2,
       TRT3.Record_Date3 AS Record_Date_wk3,
       TRT4.Record_Date4 AS Record_Date_wk4,
       CASE
           WHEN Reading_wkexp > Reading_wk2 THEN 'Up'
           WHEN Reading_wkexp < Reading_wk2 THEN 'Down'
           WHEN Reading_wkexp = Reading_wk2 THEN '-'
       END Wk1_Trend,
       CASE
           WHEN Reading_wk2 > Reading_wk3 THEN 'Up'
           WHEN Reading_wk2 < Reading_wk3 THEN 'Down'
           WHEN Reading_wk2 = Reading_wk3 THEN '-'
       END Wk2_Trend,
       CASE
           WHEN Reading_wk3 > Reading_wk4 THEN 'Up'
           WHEN Reading_wk3 < Reading_wk4 THEN 'Down'
           WHEN Reading_wk3 = Reading_wk4 THEN '-'
       END Wk3_Trend
FROM TRT
JOIN TRT1 ON TRT.ID = TRT1.ID
JOIN TRT2 ON TRT1.ID = TRT2.ID
JOIN TRT3 ON TRT2.ID = TRT3.ID
JOIN TRT4 on TRT4.ID = TRT3.ID
JOIN TRTx ON TRT.ID = TRTx.ID
--ORDER BY TRT1.ID
;