使用场景:希望通过SQL语句查询得到有签到记录的用户的连续签到天数的信息,这里的重点是连续的天数。
第一步: 如果数据库记录的是datetime类型,则需要先转成date类型;如果一个用户一天会有多条数据,则也需要按用户和日期进行去重复,保证一个用户一天只有一条数据。
SELECT CompanyID,
CAST(CreateDate AS DATE) AS Date1
FROM rec.SeeInquiry
WHERE CompanyID IS NOT NULL
GROUP BY CompanyID,
CAST(CreateDate AS DATE)
第二步: 使用row_number进行分组与排序,按用户进行分组,按时间进行排序
SELECT *,
ROW_NUMBER () OVER (PARTITION BY T.CompanyID
ORDER BY T.Date1 ASC
) AS sort1
FROM
(
SELECT CompanyID,
CAST(CreateDate AS DATE) AS Date1
FROM rec.SeeInquiry
WHERE CompanyID IS NOT NULL
GROUP BY CompanyID,
CAST(CreateDate AS DATE)
) AS T
第三步: 通过使用日期 - sort1,就会得到另一个日期,如果有连续的签到数据,则相减后的值也是相同的,通过这个值进行分组,求一个count,代码中的min与max只是为了验证数据是否正确。
例如,日期为2020-02-05,sort为1,那么相减得到2020-02-04
日期为2020-02-06,sort为2,那么相减得到2020-02-04 …依次类推
SELECT T2.CompanyID,
DATEADD(DAY, -T2.sort1, T2.Date1) AS groupInfo, --分组用
MIN(T2.Date1) AS start_date1,
MAX(T2.Date1) AS end_date1,
COUNT(1) AS continous_days --连续的天数
FROM
(
SELECT *,
ROW_NUMBER () OVER (PARTITION BY T.CompanyID
ORDER BY T.Date1 ASC
) AS sort1
FROM
(
SELECT CompanyID,
CAST(CreateDate AS DATE) AS Date1
FROM rec.SeeInquiry
WHERE CompanyID IS NOT NULL
GROUP BY CompanyID,
CAST(CreateDate AS DATE)
) AS T
) AS T2
GROUP BY T2.CompanyID,
DATEADD(DAY, -T2.sort1, T2.Date1)
第四步: 最后对连续的天数按每个用户进行求max,就能得到每一个用户最大的连续签到数据。在此之后,如果想有其它的表连操作,看情况连表就可以了。
SELECT T3.CompanyID,
MAX(T3.continous_days) AS maxday
FROM
(
SELECT T2.CompanyID,
DATEADD(DAY, -T2.sort1, T2.Date1) AS login_group,
MIN(T2.Date1) AS start_date1,
MAX(T2.Date1) AS end_date1,
COUNT(1) AS continous_days
FROM
(
SELECT *,
ROW_NUMBER () OVER (PARTITION BY T.CompanyID
ORDER BY T.Date1 ASC
) AS sort1
FROM
(
SELECT CompanyID,
CAST(CreateDate AS DATE) AS Date1
FROM rec.SeeInquiry
WHERE CompanyID IS NOT NULL
GROUP BY CompanyID,
CAST(CreateDate AS DATE)
) AS T
) AS T2
GROUP BY T2.CompanyID,
DATEADD(DAY, -T2.sort1, T2.Date1)
) AS T3
GROUP BY T3.CompanyID;
总结:此代码主要思路
1、利用row_number的PARTITION BY 对数据进行分组与排序;
2、利用日期-排序,如果得到的结果还是同一天,则说明是连续;