按日期限制

时间:2015-04-04 15:40:17

标签: sql postgresql

我有一个任务表,我查询并尝试按截止日期对结果进行分组,并将每组返回的任务数量限制为10个。

     id    |     name         | duedate
---------------------------------------------
    101    |      task1       | 2015-03-05
    102    |      task2       |
    104    |      task3       | 2015-03-06
    105    |      task4       | 2015-03-07
    106    |      task5       | 
    107    |      task6       | 2015-02-28
    108    |      task7       | 2015-02-27
    109    |      task8       | 2015-02-05
    111    |      task9       | 

我尝试将任务分为4组,并将每组限制为10个任务:

  1. Duedate =今天
  2. Duedate =今天 - 7天
  3. Duedate =今天+ 7天
  4. Duedate = null
  5. 我使用postgres窗口功能来实现这一目标。问题是我无法使用"分区"对于团体。

    到目前为止,我已经设法提出这个:

    select * from ( select id,name,duedate,row_number()  
      OVER (PARTITION BY duedate order by duedate)  as rownum from tasks
      ) tmp where rownum < 10;
    

    这不会起作用,因为它为每个人都创造了一个小组。

    是否可以不使用多个查询?

2 个答案:

答案 0 :(得分:0)

您可以在case

中使用partition by表达式
select *
from (select id, name, duedate,
             row_number()  over (partition by (case when duedate = CURRENT_DATE then 1
                                                    when duedate >= CURRENT_DATE - interval '7 day' and duedate < CURRENT_DATE then 2
                                                    when duedate <= CURRENT_DATE + interval '7 day' and duedate > CURRENT_DATE then 3
                                               end)
                                 order by duedate) as rownum
      from tasks
      where duedate >= CURRENT_DATE - interval '7 day' and
            duedate <= CURRENT_DATE + interval '7 day'
     ) tmp
where rownum < 10;

答案 1 :(得分:0)

如果您的目的是形成代表

的四个小组
  1. 今天
  2. 一周前和今天(今天除外)之间的项目
  3. 自今天起一周内(今天除外)的物品
  4. 缺少duedate
  5. 并忽略所有其他日期,然后这样的事情会起作用:

    select *,
      -- I left the case expression in to show what it does.
      case 
        when Duedate = current_date 
        then 1
        when Duedate >= current_date - interval '7 days' 
         and Duedate < current_date 
        then 2
        when Duedate <= current_date + interval '7 days' 
         and Duedate > current_date 
        then 3
      end as grouping
    from ( 
      select 
        id,
        name,
        duedate,
        row_number() OVER (PARTITION BY 
          case 
            when Duedate = current_date then 1
            when Duedate >= current_date - interval '7 days' 
                           and Duedate < current_date 
                           then 2
            when Duedate <= current_date + interval '7 days' 
                           and Duedate > current_date 
                           then 3
          end 
          order by duedate
      ) as rownum 
      from tasks
      where (Duedate >= current_date - interval '7 days'
        and Duedate <= current_date + interval '7 days') 
         or Duedate is null
    
    ) tmp where rownum < 10;
    

    Sample SQL Fiddle(略微修改日期以获得一些结果)

    这会产生类似于此的结果:

    |  id |   name |                 duedate | rownum | grouping |
    |-----|--------|-------------------------|--------|----------|
    | 112 | task10 | April, 04 2015 00:00:00 |      1 |        1 |
    | 113 | task11 | April, 04 2015 00:00:00 |      2 |        1 |
    | 107 |  task6 | March, 28 2015 00:00:00 |      1 |        2 |
    | 108 |  task7 | March, 29 2015 00:00:00 |      2 |        2 |
    | 104 |  task3 | April, 06 2015 00:00:00 |      1 |        3 |
    | 105 |  task4 | April, 07 2015 00:00:00 |      2 |        3 |
    | 101 |  task1 | April, 11 2015 00:00:00 |      3 |        3 |
    | 102 |  task2 |                  (null) |      1 |   (null) |
    | 106 |  task5 |                  (null) |      2 |   (null) |
    | 111 |  task9 |                  (null) |      3 |   (null) |