使用SQL查询选择最近30天

6

我想知道过去30天内星期一到星期日的数量。我是否可以选择最近30天的日期和星期几,而不需要实际的数据库表?类似于:

SELECT --everything between
convert(date,GETDATE()), DATENAME(DW, GETDATE())
--and
convert(date,GETDATE() - 30), DATENAME(DW, GETDATE())

嗯...什么?你是从临时表还是变量表中选取呢?无论哪种方式,答案都是肯定的,但是你的代码并不是非常理想。 - Tejs
@Tejs - 我修改了我的问题。我想知道过去30天内每个星期几被访问了多少次。 - MrM
6个回答

13

您可以使用递归CTE:

;WITH CTE AS
(
    SELECT convert(date,GETDATE()) sDate, DATENAME(DW, GETDATE()) sDayofWeek
    UNION ALL
    SELECT DATEADD(DAY,-1,sDate), DATENAME(DW, DATEADD(DAY,-1,sDate))
    FROM CTE
    WHERE sDate > GETDATE()-29
)
SELECT * FROM CTE

@user54197 -- 你可能想看看我的答案--更快。 - Hogan
@Hogan - 是的,但我的回答是针对原始问题的,而不是现在的问题。无论如何,你的答案对于新问题是正确的,op应该采用它。 - Lamak
感谢您的评论。我想知道原帖作者实际想要什么。 - Hogan

1

嗯,有几种方法可以做到这一点。

  1. 您可以使用循环和INSERT语句填充临时表,然后选择表的内容。实际上,您可以创建一个表值UDF来完成此操作。
  2. 您还可以创建30个SELECT语句,并将它们全部联合在一起。但是,坦率地说,我认为您最好选择选项1。

预计时间:思考一下,如果您想要过去30天每天的数量,您可能只需进行一些数学运算即可,而无需返回30条记录。

在任何30天的周期内,每周有4个实例,再加上2天。因此,您真正需要知道的就是您所在周期的第一天和第二天是星期几。这些星期有5个实例。


1
WITH cteCount AS (
    SELECT DATENAME(dw, GETDATE()) dw, 1 ix 
    UNION ALL 
    SELECT DATENAME(dw, DATEADD(d, -ix, GETDATE())), ix+1 FROM cteCount WHERE ix<30
)
SELECT dw, COUNT(1) cnt FROM cteCount GROUP BY dw

1

几种解决方案:

SELECT ... From ... WHERE date > DATEADD(year, -1, GETDATE())

另外,我认为这个语句也适用于MySQL:

select date_sub(now(),interval 30 day)as Datebefore30days;

1

我很懒,只是加载一个临时表,然后在该临时表上执行分组选择

DECLARE @tmpDates TABLE (calDate DATETIME)
DECLARE @beginDate DATETIME
SET @beginDate = DATEADD(day,-30,GETDATE())
WHILE @beginDate < GETDATE()
BEGIN
    INSERT INTO @tmpDates ([calDate]) VALUES (@beginDate)
    SET @beginDate = DATEADD(DAY,1,@beginDate)
END


SELECT DATEPART(dw,[calDate]) AS [weekDay], COUNT(1) AS [dayCount]
FROM @tmpDates
GROUP BY DATEPART(dw,[calDate])

1

最近30天每个星期的点击次数:

SELECT DATENAME(dw,GETDATE())+' 5 times' as results
UNION ALL
SELECT DATENAME(dw,DATEADD(day,-1,GETDATE()))+' 5 times'
UNION ALL
SELECT DATENAME(dw,DATEADD(day,-2,GETDATE()))+' 4 times'
UNION ALL
SELECT DATENAME(dw,DATEADD(day,-3,GETDATE()))+' 4 times'
UNION ALL
SELECT DATENAME(dw,DATEADD(day,-4,GETDATE()))+' 4 times'
UNION ALL
SELECT DATENAME(dw,DATEADD(day,-5,GETDATE()))+' 4 times'
UNION ALL
SELECT DATENAME(dw,DATEADD(day,-6,GETDATE()))+' 4 times'

这实际上是关于将30除以7的问题


这给了我

results
Thursday 5 times
Wednesday 5 times
Tuesday 4 times
Monday 4 times
Sunday 4 times
Saturday 4 times
Friday 4 times

不寻常,但是正确的。 :) 但如果我是你,我会将其参数化以显示结果是如何获得的。 - Andriy M
@Andriy - 不确定你的意思... 你想要内联注释吗?另外,如果正确的话,为什么不点赞呢? :D - Hogan
@Andriy - 对我来说,这似乎是糟糕的编程。如果一个计算总是等于4或5,为什么要在脚本中进行计算?这只会减慢速度。30除以7是4余2。我们都在8岁时学过这个。 - Hogan
@Hogan:没错。我的观点是,你的解决方案在看来价值不大。它确实解决了眼前的问题,如果我是原帖发布者,我至少会点赞。但作为这个问题的一个潜在回答者,我发现自己可以用其他标准来评估其他回答者的帖子。特别是我发现你的解决方案虽然聪明,但是不完整,因此不值得点赞。我绝不自认为是一个模范点赞者,只是陈述了我的理由,仅此而已。 - Andriy M
1
@Hogan:我认为计算应该被包含进来,进一步澄清的原因是:30很容易变成50或100。也就是说,它只需要成为一个参数,这种情况下计算就必须被包含进来。 - Andriy M
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接