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

时间:2013-02-11 07:41:36

标签: sql-server

我有一个表Task with有一个createdDate列。我需要获得在特定月份创建的所有任务,每天不应超过4条记录。如果特定日期中有超过4条记录,那么我们只能获得首先打包的前4条记录。还有另一列CreatedTime。

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  

3 个答案:

答案 0 :(得分:0)

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

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_NUMBER与{{1}交换}或RANK,视需要而定。

答案 1 :(得分:0)

; 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 A中找到分区列(YearMonth),
  2. 然后在B中为每条记录分配一个RowNum(这可以根据您的订购citeria进行更改)
  3. 然后你得到最终结果。

答案 2 :(得分:0)

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

; 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