我正在尝试查看是否有更好的方法来实现我现在正在做的事情。例如,我需要知道过去12个月内已登录的用户总数。因此,每个连续至少十二个月每月登录一次的用户都将计入总数。
我现在这样做的方式是:查询表并获取所有用户ID和时间戳(它们处于活动状态),然后将其返回给我的C#代码。然后,使用一堆循环和LINQ来计算值(将太多的代码转储到此问题中,并且由于我试图摆脱在c#中的处理方式,因此我认为不需要这样做)。
现在这需要一些时间才能运行,我敢肯定必须有一种更好的SQL方式来执行此操作。我已经搜索过,但没有找到可让您根据重复条件进行计数的任何SQL函数。
对于一个答案,我希望得到一个示例或一个类似的SO问题的链接,或者是一篇有关实现此问题的文章。
MyUsersTable
的示例:
UserId | Timestamp
1 | '2018-12-23 00:00:00.000'
1 | '2018-11-23 00:00:00.000'
1 | '2018-10-23 00:00:00.000'
编辑:我确实考虑过使用SUM(CASE WHEN month = 1 and month = 2 and month = 3)
,但这似乎也不是一个很好的解决方案。
预期结果:
过去12个月每月至少活跃一次的用户总数。
答案 0 :(得分:2)
如果您需要在2018年每月登录的用户:
select ut.userid
from MyUsersTable ut
where timestamp >= '2018-01-01' and timestamp < '2019-01-01'
group by ut.userid
having count(distinct month(timestamp)) = 12;
答案 1 :(得分:2)
我将计算用户登录的不同月份:
SELECT userid
FROM mytable
WHERE YEAR(timestamp) = 2018
GROUP BY userid
HAVING COUNT(DISTINCT MONTH(timestamp)) = 12
答案 2 :(得分:1)
要获取连续特定月份登录的用户ID,可以使用:
/* These are your input values */ DECLARE @searchDate date = '2018-12-15' ; DECLARE @monthsToSearch int = 12 ; /* First day of search month */ DECLARE @EndDate date = DATEADD(month, DATEDIFF(month, 0, @searchDate), 0) ; /* First day of month to search from */ DECLARE @StartDate date = DATEADD(month, -@monthsToSearch, @EndDate) ; SELECT userID --, @StartDate AS startDate, @EndDate AS endDate FROM ( SELECT userID, ( (YEAR(userLoginDT)*100)+MONTH(userLoginDT) ) AS datePoint /* YYYYMM */ FROM t1 WHERE userLoginDT >= @StartDate AND userLoginDT < @EndDate ) s1 GROUP BY userID HAVING count(distinct(datePoint)) = @monthsToSearch ;
见分贝<>拨弄here 我的例子。
第一个声明的两个变量是您的输入变量。您可以在运行报表的日期输入它,然后告诉它要返回多少个月。因此,您可以搜索任意数量的月份。之后,几乎是日期操作和数学运算。
@EndDate
实际上是获取您声明的日期并计算当前正在搜索的月份的第一天。您将搜索该日期之前的任何日期。
@StartDate
从@EndDate
开始倒数,以计算要搜索的月数。
(YEAR(userLoginDT)*100)+MONTH(userLoginDT)
创建了一个整数变量,您可以GROUP BY
来获取正在搜索的月份的不同计数。这部分可以通过日历表加快。
然后你只需要使用HAVING
挑出多少重复的记录您想为@monthsToSearch
。
注意::这里有很多人可以证明,在处理日期计算和大量搜索数据时,我非常喜欢使用日历表。类似的东西可能会加快查询了一下。的