SQL - 为每周的每一天选择记录高

时间:2011-04-28 20:07:19

标签: sql sql-server-2008

它返回按CountOfRecords DESC排序的所有行。我想在这里只有七行,显示指定日期的最高值。因此,一周中的每一天应该只发生一次。这可能没有很多痛苦吗?

SELECT 
    Count(*) As CountOfRecords, 
    CAST(FLOOR(CAST([visit].[datetimeentered] AS float)) AS smalldatetime) AS DateEntered, 
    DatePart(dw, visit.datetimeentered) As DayOfTheWeek
FROM visit
INNER JOIN useragent ON useragent.useragentid = visit.useragentid
WHERE useragent.isbot = 0
GROUP BY CAST(FLOOR(CAST([visit].[datetimeentered] AS float)) AS smalldatetime), 
    DatePart(dw, visit.datetimeentered)
ORDER BY CountOfRecords DESC

EDIT1:
我认为两个答案都是相同的。我已经接受了首先发布的那个。我还要提到它可以立即起作用,而另一个则没有。当我运行marc_s的查询时,我收到以下错误:

Msg 207, Level 16, State 1, Line 29
Invalid column name 'RowNum'.
Msg 207, Level 16, State 1, Line 25
Invalid column name 'CountOfRecords'.
Msg 207, Level 16, State 1, Line 26
Invalid column name 'DateEntered'.
Msg 207, Level 16, State 1, Line 27
Invalid column name 'DayOfTheWeek'.

特别感谢marc_s指出了一个简单的方法来从日期时间获得唯一的日期部分。

2 个答案:

答案 0 :(得分:1)

在SQL Server 2005及更高版本上,您可以使用带有ROW_NUMBER()排名函数和PARTITION BY子句的CTE(公用表表达式) - 类似这样的内容:

;WITH DataByDayOfWeek AS
(
   SELECT 
      Count(*) As CountOfRecords,
      CAST(FLOOR(CAST(v.[datetimeentered] AS float)) AS smalldatetime) AS DateEntered, 
      DatePart(dw, v.datetimeentered) As DayOfTheWeek
   FROM dbo.visit v
   INNER JOIN dbo.useragent u ON u.useragentid = v.useragentid
   WHERE u.isbot = 0
   GROUP BY 
       CAST(FLOOR(CAST(v.[datetimeentered] AS float)) AS smalldatetime), 
       DatePart(dw, v.datetimeentered)
),
HighestValues AS
(
    SELECT 
       CountOfRecords,
       DateEntered,
       DayOfTheWeek,
       ROW_NUMBER() OVER(PARTITION BY DayOfTheWeek 
                         ORDER BY CountOfRecords DESC) 'RowNum'
    FROM DataByDayOfWeek
)
SELECT 
   CountOfRecords,
   DateEntered,
   DayOfTheWeek
WHERE
   RowNum = 1

让我解释一下:

  • 第一个CTE基本上对记录进行计数 - 因此每个DateEntered会有一个条目记录计数和星期几
  • 第二个CTE基于第一个CTE,它将您的数据“分区”DayOfTheWeek - 因此,对于每周的每个不同日期,您将获得一个从1开始的计数器。本周按记录计数按降序排序,因此最高值为RowNum,即1

因此,从第二个CTE中选择RowNum = 1的所有行,可以为您提供一周中每一天的最高值。

作为旁注:我相信SQL Server 2008,您可以更轻松地将日期时间转换为仅DATE的严格DATE - 没有时间 - 就像这样:

CAST(v.DateTimeEntered AS DATE)

转换为浮动然后再转移到smalldatetime再也不用了 - 试试吧!

答案 1 :(得分:1)

根据您的查询:

WITH groupedByDay AS (
  SELECT 
    Count(*) As CountOfRecords, 
    CAST(FLOOR(CAST([visit].[datetimeentered] AS float)) AS smalldatetime) AS DateEntered
  FROM visit
  INNER JOIN useragent ON useragent.useragentid = visit.useragentid
  WHERE useragent.isbot = 0
  GROUP BY CAST(FLOOR(CAST([visit].[datetimeentered] AS float)) AS smalldatetime)
),
ranked AS (
  SELECT
    CountOfRecords,
    DateEntered,
    DOW = DATENAME(dw, DateEntered),
    rank = ROW_NUMBER() OVER (PARTITION BY DatePart(dw, DateEntered)
                              ORDER BY CountOfRecords DESC)
  FROM groupedByDay
)
SELECT
  CountOfRecords,
  DateEntered,
  DOW
FROM ranked
WHERE rank = 1
ORDER BY CountOfRecords DESC

这将为表中所示的每周的每一天返回一行。如果最大值中CountOfRecords之间可能存在重复项,并且您想要全部返回,请使用RANK()代替ROW_NUMBER()