平均相交

时间:2019-01-14 14:15:06

标签: sql sql-server

我有这个数据集,我在每个班次创建一个报告来显示每小时的特定活动。例如:班次从7到15,因此报告将为: 7:00-15移动 8:00-18步

此报告包含数周和数天的过滤器,因为目的是让用户查看其轮班表现。

但是,我想将特定时间段内的活动与过去10周中同一天的同一天进行比较。例如:

我在周二的7:00时有15次移动,我想将其与过去10周中周二的7:00的平均移动次数进行比较。

我将如何在SQL中获得它! :-)

1 个答案:

答案 0 :(得分:0)

这可能会使您朝正确的方向前进。鉴于您尚未声明您的数据结构,因此我自由地假设可能是这样。

您可以在SSMS中运行以下命令来自己查看/修改结果。

首先,我创建了一个表变量来模拟假定的数据。

-- Create a dummy "shift" table --
DECLARE @shifts TABLE ( shift_id INT IDENTITY ( 1, 1 ) PRIMARY KEY, shift_date DATETIME, shift_moves INT );

然后我插入了一些虚拟数据。为了节省时间和简化起见,我在过去的十个星期中坚持使用星期二。

-- Insert ten weeks of Tuesdays --
INSERT INTO @shifts ( shift_date, shift_moves ) VALUES
  ( '11/06/2018 07:10:00', 5 )
, ( '11/13/2018 07:08:00', 12 )
, ( '11/20/2018 07:00:00', 14 )
, ( '11/27/2018 07:20:00', 15 )
, ( '12/04/2018 07:35:00', 12 )
, ( '12/11/2018 07:18:00', 11 )
, ( '12/18/2018 07:16:00', 10 )
, ( '12/25/2018 07:00:00', 12 )
, ( '01/01/2019 07:00:00', 13 )
, ( '01/08/2019 07:22:00', 15 );

表变量@shifts现在包含以下数据:

+----------+-------------------------+-------------+
| shift_id |       shift_date        | shift_moves |
+----------+-------------------------+-------------+
|        1 | 2018-11-06 07:10:00.000 |           5 |
|        2 | 2018-11-13 07:08:00.000 |          12 |
|        3 | 2018-11-20 07:00:00.000 |          14 |
|        4 | 2018-11-27 07:20:00.000 |          15 |
|        5 | 2018-12-04 07:35:00.000 |          12 |
|        6 | 2018-12-11 07:18:00.000 |          11 |
|        7 | 2018-12-18 07:16:00.000 |          10 |
|        8 | 2018-12-25 07:00:00.000 |          12 |
|        9 | 2019-01-01 07:00:00.000 |          13 |
|       10 | 2019-01-08 07:22:00.000 |          15 |
+----------+-------------------------+-------------+

我创建了一些可以传递给存储过程的参数。

-- What date are we looking at? --
DECLARE @date DATETIME = '01/08/2019';

-- How many weeks back to compare? --
DECLARE @weeks_back INT = -10;

*记住:要向后看,@ weeks_back 必须为负数。 在生产中,您将对此进行检查/处理。

接下来,我创建了两个局部变量,以帮助简化查询时使用的日期/时间。

-- Create variables for the start and end times for simplicity --
DECLARE 
    @sDT DATETIME = CAST( CONVERT( VARCHAR(10), @date, 101 ) + ' 00:00:00' AS DATETIME ),
    @eDT DATETIME = CAST( CONVERT( VARCHAR(10), @date, 101 ) + ' 23:59:59' AS DATETIME );

然后,只需使用CROSS APPLY查询数据以获取所需结果即可。

使用CROSS APPLY允许我查询所需时间范围(@weeks_back)的第二个轮班数据子集,该子集与查询的主要记录(在本例中为shift_date为01/08/2019)相关。

-- Get resultset --
SELECT
    DATEPART( hh, shift_date ) AS [shift_hour]
    , DATENAME( dw, s.shift_date ) AS [shift_day]
    , CONVERT( VARCHAR(10), s.shift_date, 101 ) AS [shift_date]
    , s.shift_moves
    , shift_avg.shift_average
FROM @shifts AS s
CROSS APPLY (

    SELECT
        AVG( a.shift_moves ) AS [shift_average]
    FROM @shifts a
    WHERE
        -- restrict to the current hour.
        DATEPART( HH, a.shift_date ) = DATEPART( HH, s.shift_date )
        -- restrict to the current day of the week.
        AND DATEPART( DW, a.shift_date ) = DATEPART( DW, s.shift_date )
        -- compare against the desired time period / weeks back.
        AND a.shift_date BETWEEN DATEADD( WW, @weeks_back, CAST( CONVERT( VARCHAR(10), s.shift_date, 101 ) AS DATETIME ) ) AND a.shift_date

) AS shift_avg
WHERE
    s.shift_date BETWEEN @sDT AND @eDT
ORDER BY
    s.shift_date;

哪个返回以下结果集:

+------------+-----------+------------+-------------+---------------+
| shift_hour | shift_day | shift_date | shift_moves | shift_average |
+------------+-----------+------------+-------------+---------------+
|          7 | Tuesday   | 01/08/2019 |          15 |            11 |
+------------+-----------+------------+-------------+---------------+

我希望这能帮助您朝着想要的方向前进,@ Aron。