在sql server中按月份和日期获取数据

问题描述:

我有一个带有createdDate列的任务表。我需要获得在特定月份创建的所有任务,每天不应该有超过4条记录。如果在特定日期有超过4条记录,那么我们只能得到第一条第一条记录。还有另一列CreatedTime。在sql server中按月份和日期获取数据

Task 
(
    id 
    ,CreatedDate 
    ,CreatedTime 

) 

结果应该是

id  CreatedDate 

1  1/1/2013 
2  1/1/2013 
3  1/1/2013 
4  1/1/2013 
5  1/2/2013 
6  1/2/2013 
7  1/2/2013 
8  1/2/2013 

使用ROW_NUMBER()在子查询或公用表表达式(CTE)。子查询的版本:

SELECT 
    * --TODO: Columns 
FROM 
    (SELECT 
     *,ROW_NUMBER() OVER (PARTITION BY CreatedDate ORDER BY CreatedTime) as rn 
    FROM 
     Task 
    ) t 
WHERE 
    rn between 1 and 4 

如果(在同一天的两行具有相同CreatedTime)曾在你的数据可能的联系,你需要把这些转化为显性的考虑,你可以换ROW_NUMBERRANKDENSE_RANK,按要求。

; WITH A AS (
SELECT ID, CreatedDate 
, convert(VARCHAR(7), CreatedDate, 121) AS YearMonth --will return something like 2012-01 
FROM Task 
), 
B AS (
SELECT ID, CreatedDate 
, ROW_NUMBER() OVER (PARTITION BY YearMonth ORDER BY CreatedDate, ID) AS RowNum 
FROM A) 
SELECT ID, CreatedDate 
FROM B 
WHERE RowNum<=4 
ORDER BY ID 

这适用于SQL 2005及更高版本。

  1. 首先在CTE一个你发现你的分区列(YearMonth)
  2. 那么B中分配每条记录都有一个ROWNUM(这是可以改变的基础上您的订购citeria)
  3. ,然后你会得到最终的结果。
+0

感谢您的回复。我做了一些改变,并在这里得到了解决方案。 – 2013-02-11 10:06:56

+0

是的,上午10点前回复了这个:)。现在我看到你想要每天的第一个结果。如果你转换为Varchar(10),你会得到一整天(没有时间),你很好去。 – Daniel 2013-02-11 16:39:51

感谢您的回复。我做了一些改变,并在这里得到了解决方案。

; WITH A 
AS 
(
SELECT ID, CreatedDate , DAY(CreatedDate) AS Day 
FROM Task 
WHERE CreatedDate BETWEEN '01/01/2013 00:00:00' AND '01/31/2013 23:59:59' 
) 
, 
B AS 
(
    SELECT 
    ROW_NUMBER() OVER (PARTITION BY Day ORDER BY CreatedDate, ID) AS RowNum 
    ,* 
    FROM A 
) 


select 
DAY(CreatedDate) as Day1 
, MONTH(CreatedDate) as Month 
, YEAR(dueDate) as Year 
, * 
from B 
WHERE RowNum <= 4 
order by Year,Month,Day1, CreatedDate