SQL Server计算每个用户每天的平均得分,但某些用户在某些天没有记录得分

时间:2016-07-25 11:26:28

标签: sql-server tsql

这是我的第一篇文章,所以请放轻松跟我:-)。我试图获得一个SQL查询,该查询将给出每个用户每天的平均分数。数据用于绘制图表,因此我需要为每个用户提供一致的时间表。我遇到的问题是某些用户可能没有特定日期的任何数据,所以我需要这个只返回0.以下是源数据和所需结果的示例(注意user02没有数据为09 / 07/2016):

 RAW data                           Desired results

 USER    DATE        SCORE          USER    DATE        AVERAGE_SCORE
 user01  08/07/2016  0.66667        user01  08/07/2016  0.16667
 user01  08/07/2016  0.33333        user01  09/07/2016  0.66667
 user01  08/07/2016  -0.5           user01  10/07/2016  0.72222
 user01  09/07/2016  0.33333        user02  08/07/2016  0.10317
 user01  09/07/2016  0.66667        user02  09/07/2016  0.00000 <--return 0
 user01  09/07/2016  1              user02  10/07/2016  0.16270
 user01  10/07/2016  0.66667
 user01  10/07/2016  1
 user01  10/07/2016  0.5
 user02  08/07/2016  0.16667
 user02  08/07/2016  -0.14286
 user02  08/07/2016  0.28571
 user02  10/07/2016  0.66667
 user02  10/07/2016  0.57143
 user02  10/07/2016  -0.75

在生产数据库中,表中可能有数十个用户,因此我需要考虑到这一点。我不确定解决这个问题的最佳方法,我以前做过一些简单的SQL数据库工作,但是这个我很挣扎。任何帮助或建议最受赞赏。

4 个答案:

答案 0 :(得分:0)

试试这个......

select 
   [USER], 
   DATE, 
   avg(SCORE) 
from tbl_name 
group by DATE,[USER] 
Order by DATE,[USER]

答案 1 :(得分:0)

SELECT USERID, SUM(Scores) / (DATEDIFF(day,MIN(DATE),MAX(DATE))+1) 
as AVERAGE_PER_DAY  
    from table_name 
       GROUP BY USERID

如果您想在期末避免不活动的问题(例如,发布到2周前),这是一个合理的选择

SELECT USERID, SUM(Scores) / (DATEDIFF(day,MIN(DATE),getdate())+1) 
as AVERAGE_PER_DAY  
    from table_name 
       GROUP BY USERID

答案 2 :(得分:0)

Unmodified

答案 3 :(得分:0)

试试这个

DECLARE @MinDate DATETIME
DECLARE @MaxDate DATETIME

DECLARE @TBL TABLE (u NVARCHAR(50), d DATETIME, Score DECIMAL(10, 6))

INSERT INTO @TBL
SELECT 'user01' u,  '2016.07.08' d,  0.66667  SCORE union all      
select 'user01' u,  '2016.07.08' d,  0.33333  SCORE union all      
select 'user01' u,  '2016.07.08' d,  -0.5     SCORE union all      
select 'user01' u,  '2016.07.09' d,  0.33333  SCORE union all      
select 'user01' u,  '2016.07.09' d,  0.66667  SCORE union all       
select 'user01' u,  '2016.07.09' d,  1        SCORE union all      
select 'user01' u,  '2016.07.10' d,  0.66667    SCORE union all
select 'user01' u,  '2016.07.10' d,  1      SCORE union all
select 'user01' u,  '2016.07.10' d,  0.5        SCORE union all
select 'user02' u,  '2016.07.08' d,  0.16667    SCORE union all
select 'user02' u,  '2016.07.08' d,  -0.14286   SCORE union all
select 'user02' u,  '2016.07.08' d,  0.28571    SCORE union all
select 'user02' u,  '2016.07.10' d,  0.66667    SCORE union all
select 'user02' u,  '2016.07.10' d,  0.57143    SCORE 


SELECT 
    @MinDate = MIN(d),
    @MaxDate = MAX(d)
FROM @TBL

;WITH Dates(dt)
AS
(
    SELECT @MinDate dt
    UNION ALL
    SELECT DATEADD(dd, 1, dt) AS dt
    FROM Dates
    WHERE 
        dt < @MaxDate
)

-- Query

SELECT 
    u,
    d,
    AVG(SCORE) SCORE        
FROM
    @TBL
GROUP BY 
    u,
    d

UNION ALL   

SELECT
    A.u,
    D.dt,
    0 Score
FROM
    Dates D CROSS JOIN
    (SELECT DISTINCT u FROM @TBL) A
WHERE
    EXISTS
    (
        SELECT * FROM 
        (
            SELECT 
                u,
                d,
                MIN(d) OVER (PARTITION BY u ORDER BY (SELECT null)) MinDate,
                MAX(d) OVER (PARTITION BY u ORDER BY (SELECT null)) MaxDate
            FROM
                @TBL                
        ) T
        WHERE
            T.u = A.u AND                
            D.dt BETWEEN T.MinDate AND T.MaxDate                 
    ) AND
    D.dt NOT IN (
            SELECT T.d FROM @TBL T  
            WHERE
                T.u = A.u
    )
    ORDER BY u, d

输出:

u          d           SCORE
--------- -----------  -------------
user01    2016-07-08   0.166666
user01    2016-07-09   0.666666
user01    2016-07-10   0.722223
user02    2016-07-08   0.103173
user02    2016-07-09   0.000000
user02    2016-07-10   0.619050