【问题标题】:Help with SQL to get Hits per day for today and 1 month prior使用 SQL 帮助获取今天和 1 个月前的每日点击次数
【发布时间】:2009-11-30 23:25:43
【问题描述】:

我现在有这个 SQL:

CREATE PROCEDURE dbo.sel_Track_HitsLast30Days(
@projectID int
)
AS
BEGIN
 DECLARE @FirstDay smalldatetime, @NumberOfMonths int, @priorMonth smalldatetime
set @priorMonth = (SELECT CAST(
(
STR( YEAR( dateadd(m,-1, getDate()) ) ) + '/' +
STR( MONTH( dateadd(m,-1, getDate()) ) ) + '/' +
STR( DAY( dateadd(m,-1, getDate()) ) )
)
AS DateTime 
))
Select @FirstDay = @priorMonth, @NumberOfMonths = 1
;WITH Days AS (
SELECT @FirstDay as CalendarDay
UNION ALL
SELECT DATEADD(d, 1, CalendarDay) as CalendarDay
FROM Days
WHERE DATEADD(d, 1, CalendarDay) < DATEADD(m, @NumberOfMonths, @FirstDay+1)
)
SELECT calendarday,foundDate.TotalbyDate,foundDate.date FROM Days

LEFT OUTER JOIN (

SELECT
COUNT(LEFT(visitDateTime, 11)) AS TotalbyDate,substring(convert( char(10), CONVERT( char(10), visitDateTime, 121 ) ), 1, 11) AS date

FROM
  dbo.TrackingData
WHERE
  visitDateTime >= dateadd(d, datediff(d, 0, getdate()), -30) and projectID = @projectID
  GROUP BY substring(convert( char(10), CONVERT( char(10), visitDateTime, 121 ) ), 1, 11)


) foundDate on foundDate.date = CalendarDay

order by 
CalendarDay Desc
END

这行得通,但它没有考虑 31 天的月份,并且由于某种原因我没有返回今天的日期。

【问题讨论】:

  • 我相信这也可以得到更好的优化;)
  • 我真的很想帮忙,但我只为大笔现金寻找那种 SQL :)
  • 我也没有提到我需要在可能没有任何结果的日期旁边显示空值。

标签: sql-server datetime


【解决方案1】:

试试这个(使用 AdventureWorks 作为示例数据库)

DECLARE @today datetime, @NumberOfMonths int, @FirstDay smalldatetime
SELECT  @today = '2004-03-09', -- getdate(), tests only
        @NumberOfMonths = 1, 
        @FirstDay = CAST(FLOOR(CAST(
                         DATEADD(M, -1, @today) AS float)) AS datetime);
WITH Days AS
(
    SELECT @FirstDay AS  CalendarDay UNION ALL
    SELECT DATEADD(d, 1, CalendarDay) AS CalendarDay FROM Days
    WHERE  DATEADD(d, 1, CalendarDay) < DATEADD(m, @NumberOfMonths, @FirstDay+1)
)
SELECT   CONVERT(varchar(10), CalendarDay, 111) as [Date],
         COUNT(TransactionDate) as [Count] 
FROM     Days LEFT JOIN Production.TransactionHistory
ON       TransactionDate = Days.CalendarDay
GROUP BY CalendarDay
ORDER BY CalendarDay

会输出

日期计数 ---------- ------------ 2004/02/09 272 2004/02/10 308 2004/02/11 264 2004/02/12 265 2004/02/13 250 ...

编辑:更新为包括所有间隔日期

【讨论】:

  • 这似乎无法正常工作。分组对我不起作用,我应该在哪里使用@firstDayLastMonth?谢谢
  • 我弄清楚了为什么分组不起作用。它与包含的日期时间有关。
【解决方案2】:

这里是鲁本回答的修改版:

DECLARE  @today             DATETIME,
         @firstDayLastMonth DATETIME,
         @daysCount int

SET @today = getDate()
SET @firstDayLastMonth = Dateadd(m,-1,Dateadd(d,-Day(@today) + 1,@today))
Set @daysCount = (select datepart(dd,dateadd(dd,-1,dateadd(mm,1,cast(cast(year(@firstDayLastMonth) as varchar)+'-'+cast(month(@firstDayLastMonth) as varchar)+'-01' as datetime)))))

SELECT   substring(convert( char(10), CONVERT( char(10), visitDateTime, 121 ) ), 1, 11) AS [Date], Count(* ) AS [Count]
FROM     dbo.TrackingData
WHERE    visitdatetime >= Dateadd(d,-@daysCount,@today)
GROUP BY substring(convert( char(10), CONVERT( char(10), visitDateTime, 121 ) ), 1, 11)
ORDER BY substring(convert( char(10), CONVERT( char(10), visitDateTime, 121 ) ), 1, 11)

【讨论】:

    【解决方案3】:

    好的,我明白了。鲁本斯给了我一个想法,所以我像这样修改了我的 SQL:

    DECLARE  @FirstDay       SMALLDATETIME,
             @NumberOfMonths INT,
             @priorMonth     SMALLDATETIME,
             @firstDayLastMonth DateTime,
             @daysCount int
    set @firstDayLastMonth = dateadd(m, -1,      dateadd(d, -day(getDate()) + 1, getDate()))
    set @daysCount = (select datepart(dd,dateadd(dd,-1,dateadd(mm,1,cast(cast(year(@firstDayLastMonth) as varchar)+'-'+cast(month(@firstDayLastMonth) as varchar)+'-01' as datetime)))))
    SET @priorMonth = (SELECT Cast((Str(Year(Dateadd(m,-1,Getdate()))) + '/' + Str(Month(Dateadd(m,-1,Getdate()))) + '/' + Str(Day(Dateadd(m,-1,Getdate())))) AS DATETIME))
    
    Declare @before dateTime
    Set @before = Dateadd(d,-@daysCount,getdate())
    SELECT @FirstDay = @before,
           @NumberOfMonths = 1;
    
    WITH days
         AS (SELECT @FirstDay AS calendarday
             UNION ALL
             SELECT Dateadd(d,1,calendarday) AS calendarday
             FROM   days
             WHERE  Dateadd(d,1,calendarday) <= Dateadd(m,@NumberOfMonths,@FirstDay))
    
     SELECT   Substring(Convert(CHAR(10),Convert(CHAR(10),calendarday,101)),
                                                 1,11) ,
             founddate.totalbydate,
             founddate.DATE
    FROM     days  
     LEFT OUTER JOIN (SELECT   Count(Left(visitdatetime,11)) AS totalbydate,
                                       Substring(Convert(CHAR(10),Convert(CHAR(10),visitdatetime,101)),
                                                 1,11) AS DATE
                              FROM     dbo.trackingdata
                              WHERE    visitdatetime >= Dateadd(d,Datediff(d,0,Getdate()),-29)
                                       AND projectid = 131
                              GROUP BY Substring(Convert(CHAR(10),Convert(CHAR(10),visitdatetime,101)),
                                                 1,11)) founddate
               ON founddate.DATE = Substring(Convert(CHAR(10),Convert(CHAR(10),calendarday,101)),
                                                 1,11)
    

    【讨论】:

    • 为什么需要Substring(Convert(CHAR(10),Convert(CHAR(10),calendarday,101)),1,11)
    • 我不想显示时间。它按日期和时间分组,而不仅仅是按日期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    相关资源
    最近更新 更多