如何计算不同的登录

时间:2018-12-13 15:46:50

标签: sql sql-server

我目前每天都有不同数量的用户登录。

我想添加另一列,以了解过去7天至少登录一次的用户数量。

;WITH cte (login_date,  years, iso_week, months, emails) AS
(
    SELECT 
        CAST(a.login_time AS Date),
        DATEPART(YEAR, a.login_time),
        DATEPART(ISO_WEEK, a.login_time),
        DATEPART(MONTH, a.login_time),
        COUNT(DISTINCT a.email) AS Total
    FROM 
        database.log AS a WITH(NOLOCK)
    GROUP BY 
        CAST(a.login_time AS Date),
        DATEPART(YEAR, a.login_time),
        DATEPART(ISO_WEEK, a.login_time),
        DATEPART(MONTH, a.login_time)
)

现在,如果我尝试

SELECT 
    *,
    SUM(emails) OVER (PARTITION BY years, iso_weeks
                      ORDER BY login_date
                      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS counts_week
FROM
    cte

这基本上增加了每天登录一次化妆的时间,但这与我想要的相反。这不是7天不同电子邮件登录的总和,而是一周内登录的唯一电子邮件

因此,如果我以三封电子邮件为例,我应该在emails_week列中包含以下内容

+------------+-------+----------+--------+--------+-------------+
| login_date | years | iso_week | months | emails | emails_week |
+------------+-------+----------+--------+--------+-------------+
| 2018-12-07 |  2018 |       49 |     12 |      2 |           2 |
| 2018-12-08 |  2018 |       49 |     12 |      2 |           2 |
| 2018-12-09 |  2018 |       49 |     12 |      1 |           2 |
| 2018-12-10 |  2018 |       50 |     12 |      1 |           3 |
| 2018-12-11 |  2018 |       50 |     12 |      3 |           3 |
| 2018-12-12 |  2018 |       50 |     12 |      1 |           3 |
+------------+-------+----------+--------+--------+-------------+

2 个答案:

答案 0 :(得分:1)

肯定有一种更漂亮的方法可以执行此操作-但是-我已经编辑了SQL以根据ISO周编号检查每周。基本上,使用星期数来确定不同电子邮件计数的开始和结束日期。这个新版本使用多个CTE首先获取日期列表及其星期编号。第二个CTE(ldetails)在[login_time]上不再包含您的分组,然后我将其与星期数的结果一起加入。

设置

Declare @tbl Table
(
login_time Datetime,
email VarChar(50)
)
Insert Into @tbl Values 
('2018-12-02','email@domain.com'),
('2018-12-02','emailyyyy@domain.com'),
('2018-12-07','emailxx@domain.com'),
('2018-12-07','emailzzz@domain.com'),
('2018-12-07','emailzzz@domain.com'),
('2018-11-07','email@domain.com'),
('2018-11-07','emailx@domain.com'),
('2018-12-01','email@domain.com'),
('2018-12-11','email@domain.com')

查询

;With ldates As
(
Select Cast(Login_time As Date) As Login_Date,Max(DATEPART(YEAR, login_time)) As [Year],Max(DATEPART(ISO_WEEK, login_time)) As [Week] From @tbl
Group By Login_time
),

 ldetails As
(
    SELECT 
        --CAST(a.login_time AS Date) As lTime,
        DATEPART(YEAR, a.login_time) As [Year]
        ,DATEPART(ISO_WEEK, a.login_time) As [Week]
        ,DATEPART(MONTH, a.login_time) As [Month]
        ,Count (Distinct email) As tot
        ,COUNT(DISTINCT (Case When login_time Between DateAdd(DD,-7,GETDATE()) And GetDate() Then email Else Null End)) AS Total

       ,Count(Distinct
        (Case When login_time Between  
          (DATEADD(DAY, (7 * (DATEPART(ISO_WEEK, login_time)-1)), Cast(DATEPART(YEAR, login_time) As Char(4)) + '-01-01' ))  And 
          (DATEADD(DAY, (7 * (DATEPART(ISO_WEEK, login_time)-1)) +7, Cast(DATEPART(YEAR, login_time) As Char(4)) + '-01-01' )) 
          Then email Else Null End
        )) AS Totalyy

    FROM @tbl AS a 
    GROUP BY 
        --CAST(a.login_time AS Date),
        DATEPART(YEAR, a.login_time),
        DATEPART(ISO_WEEK, a.login_time),
        DATEPART(MONTH, a.login_time)
)
Select lDates.login_Date,ldetails.[Year],ldetails.[Week],ldetails.[Month],ldetails.tot,ldetails.Total,ldetails.Totalyy From ldetails 
Inner JOIN
lDates On ldetails.[Week] = lDates.[Week] And ldetails.[Year] = lDates.[Year]

结果

login_Date  Year    Week    Month   tot Total   Totalyy
2018-11-07  2018    45      11      2   0       2
2018-12-01  2018    48      12      2   0       2
2018-12-02  2018    48      12      2   0       2
2018-12-07  2018    49      12      2   2       2
2018-12-11  2018    50      12      1   1       1

答案 1 :(得分:-2)

您是否尝试过使用COUNT(DISTINCT ...)?