如何为给定的开始日期和结束日期分配支付期间编号

时间:2019-05-10 15:59:39

标签: postgresql function

我有一张表,上面有付款期的开始和结束日期。

  • 期间长度(天)不是静态的。范围是0到24。
  • 给定年份的付款期数可以为24-28。
  • 唯一固定的是第一个开始日期是2000年12月31日,下一个开始日期是 开始日期在上一个结束日期之后,例如1st结束日期= 2001年1月13日,第二个开始日期= 2001年1月14日。
  • 时间进展时,新的付款期将添加到表中。

我需要分配给定日历年的支付期号。规则是1月1日为期间1,即使其开始日期为上一年的12月。例如,1/31 / 2000-1 / 13/2001应该是2001年的期间1。如果在支付期间中包含明年的1月1日,则明年的期间1开始(12/30 / 2001-1 / 12/2002是2002年的支付期1)。

我需要为PostgreSQL或PostgreSQL函数创建一个查询。我想将期间1分配给目标年份中的最小日期,并递增支付期间编号,直到支付期间达到28或日历年结束(在下一年的1/1之前)。我不确定自己的逻辑以及SELECT语句中使用表中不存在的calendar_pp的部分。

开始结束

1/14/2001    1/27/2001<br/>
1/28/2001    2/10/2001<br/>
2/11/2001    2/24/2001<br/>
2/25/2001    3/10/2001<br/>
3/11/2001    3/24/2001<br/>
3/25/2001    4/7/2001<br/>
4/8/2001    4/21/2001<br/>
4/22/2001    5/5/2001<br/>
5/6/2001    5/19/2001<br/>
5/20/2001    6/2/2001<br/>
6/3/2001    6/16/2001<br/>
6/17/2001    6/30/2001<br/>
7/1/2001    7/14/2001<br/>
7/15/2001    7/28/2001<br/>
7/29/2001    8/11/2001<br/>
8/12/2001    8/25/2001<br/>
8/26/2001    9/8/2001<br/>
9/9/2001    9/22/2001<br/>
9/23/2001    9/30/2001<br/>
10/1/2001    10/6/2001<br/>
10/7/2001    10/20/2001<br/>
10/21/2001    11/3/2001<br/>
11/4/2001    11/17/2001<br/>
11/18/2001    12/1/2001<br/>
12/2/2001    12/15/2001<br/>
12/16/2001    12/29/2001<br/>
12/30/2001    1/12/2002<br/>
CREATE OR REPLACE FUNCTION calendar_pp(end_date DATE) 
RETURNS TABLE (
start_date_col DATE,
end_date_col DATE,
calendar_pp INTEGER) 
AS $$

DECLARE
calendar_pp INTEGER ; 
counter INTEGER := 0 ;
start_date DATE := TO_CHAR(TO_DATE(begin_payperiod_date,'MM/DD/YY'),'MM/DD') ;
end_date_year INTEGER := CAST((TO_CHAR(TO_DATE(min(end_payperiod_date),'MM/DD/YY'),'YYYY')) AS INTEGER) ;
target_year INTEGER := 2001 ; --1st pay period = 12/31/2000-1/13/2001

BEGIN
    WHILE counter <= 28 LOOP --max pay period = 28
        counter := counter + 1 ; 
        calendar_pp := calendar_pp + 1 ; 
        end_date_year := end_date_year + 1 ;
        target_year := target_year + 1 ;

    --assign pay period starting with 1 till end_date becomes next year
    RETURN QUERY
    SELECT TO_DATE(begin_payperiod_date,'MM/DD/YY'), TO_DATE(end_payperiod_date,'MM/DD/YY'), calendar_pp
    FROM actacc.payperiod_conversion_all_years
    WHERE end_date_year = target_year AND calendar_pp is null
    order by TO_DATE(begin_payperiod_date,'MM/DD/YY')
END LOOP; 

END; $$

LANGUAGE 'plpgsql' ;

这是预期的结果。

开始结束付款期

1/14/2001    1/27/2001    2<br/>
1/28/2001    2/10/2001    3<br/>
2/11/2001    2/24/2001    4<br/>
2/25/2001    3/10/2001    5<br/>
3/11/2001    3/24/2001    6<br/>
3/25/2001    4/7/2001    7<br/>
4/8/2001    4/21/2001    8<br/>
4/22/2001    5/5/2001    9<br/>
5/6/2001    5/19/2001    10<br/>
5/20/2001    6/2/2001    11<br/>
6/3/2001    6/16/2001    12<br/>
6/17/2001    6/30/2001    13<br/>
7/1/2001    7/14/2001    14<br/>
7/15/2001    7/28/2001    15<br/>
7/29/2001    8/11/2001    16<br/>
8/12/2001    8/25/2001    17<br/>
8/26/2001    9/8/2001    18<br/>
9/9/2001    9/22/2001    19<br/>
9/23/2001    9/30/2001  20<br/>
10/1/2001    10/6/2001  21<br/>
10/7/2001    10/20/2001 22<br/>
10/21/2001    11/3/2001 23<br/>
11/4/2001    11/17/2001 24<br/>
11/18/2001    12/1/2001 25<br/>
12/2/2001    12/15/2001 26<br/>
12/16/2001    12/29/2001    27<br/>
12/30/2001    1/12/2002 1<br/>

1 个答案:

答案 0 :(得分:0)

我不确定这28个要求。您是说即使我们不在1月1日附近,工资期也应该重新设置?假设这是不正确的,我认为这应该可行:

with dates as (SELECT start_date, end_date
  FROM (VALUES
('12/31/2000'::date,'1/13/2001'::date),
('1/14/2001','1/27/2001'),
('1/28/2001','2/10/2001'),
('2/11/2001','2/24/2001'),
('2/25/2001','3/10/2001'),
('3/11/2001','3/24/2001'),
('3/25/2001','4/7/2001'),
('4/8/2001','4/21/2001'),
('4/22/2001','5/5/2001'),
('5/6/2001','5/19/2001'),
('5/20/2001','6/2/2001'),
('6/3/2001','6/16/2001'),
('6/17/2001','6/30/2001'),
('7/1/2001','7/14/2001'),
('7/15/2001','7/28/2001'),
('7/29/2001','8/11/2001'),
('8/12/2001','8/25/2001'),
('8/26/2001','9/8/2001'),
('9/9/2001','9/22/2001'),
('9/23/2001','9/30/2001'),
('10/1/2001','10/6/2001'),
('10/7/2001','10/20/2001'),
('10/21/2001','11/3/2001'),
('11/4/2001','11/17/2001'),
('11/18/2001','12/1/2001'),
('12/2/2001','12/15/2001'),
('12/16/2001','12/29/2001'),
('12/30/2001','1/12/2002')
) v (start_date, end_date)
)
select start_date, end_date, rank() OVER (partition by date_trunc('year', end_date) ORDER BY end_date) FROM dates;
 start_date |  end_date  | rank
------------+------------+------
 2000-12-31 | 2001-01-13 |    1
 2001-01-14 | 2001-01-27 |    2
 2001-01-28 | 2001-02-10 |    3
 2001-02-11 | 2001-02-24 |    4
 2001-02-25 | 2001-03-10 |    5
 2001-03-11 | 2001-03-24 |    6
 2001-03-25 | 2001-04-07 |    7
 2001-04-08 | 2001-04-21 |    8
 2001-04-22 | 2001-05-05 |    9
 2001-05-06 | 2001-05-19 |   10
 2001-05-20 | 2001-06-02 |   11
 2001-06-03 | 2001-06-16 |   12
 2001-06-17 | 2001-06-30 |   13
 2001-07-01 | 2001-07-14 |   14
 2001-07-15 | 2001-07-28 |   15
 2001-07-29 | 2001-08-11 |   16
 2001-08-12 | 2001-08-25 |   17
 2001-08-26 | 2001-09-08 |   18
 2001-09-09 | 2001-09-22 |   19
 2001-09-23 | 2001-09-30 |   20
 2001-10-01 | 2001-10-06 |   21
 2001-10-07 | 2001-10-20 |   22
 2001-10-21 | 2001-11-03 |   23
 2001-11-04 | 2001-11-17 |   24
 2001-11-18 | 2001-12-01 |   25
 2001-12-02 | 2001-12-15 |   26
 2001-12-16 | 2001-12-29 |   27
 2001-12-30 | 2002-01-12 |    1
(28 rows)