2011-04-28 129 views
0

它返回按CountOfRecords DESC排序的所有行。我想在这里只有七排,显示特定日期的最高价值。所以一周中的每一天都应该只发生一次。这可能没有很多痛苦吗?SQL - 选择一周中的每一天的最高记录数

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您指出一个简单的方法来获得仅从日期时间的日期部分。

+1

你已经将数据分组在看起来是你问题的正确方法 - 是否有一个原因,你不能添加MAX(fieldname),其中fieldname是你想要的最高可用值的字段 - 到你的SELECT ? – 2011-04-28 20:11:26

+0

什么数据库产品和版本?它闻起来像SQL Server。如果是这样,什么版本? – Thomas 2011-04-28 20:21:30

+0

我没有提到这是SQL Server 2008.我试过了你的建议,但它没有奏效。 – HK1 2011-04-28 20:21:46

回答

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()

1

在SQL Server 2005和更新,你可以使用一个CTE(公共表表达式)与ROW_NUMBER()排名功能和PARTITION BY条款 - 这样的事情:

;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 - 试试吧!