Postgresql 创建循环以插入日期范围的日期

Postgresql 创建循环以插入日期范围的日期,postgresql,Postgresql,背景: 员工提交带薪假期申请的假期管理系统 我需要为每个员工假期请求为给定的日期范围创建半天 源表: 存储所有请求的请求,每个员工一行 id (bigint-PK) begin_date (date) begin_in_afernoon (bool) end_date (date) end_in_morning (bool) UserID (int) 样本数据: 目标表: 缺勤半天 样本数据: 我一直在研究如何为每个员工请求创建循环,以便在半天缺勤表中插入新行 提前感谢未经个人测试。。但应围绕

背景: 员工提交带薪假期申请的假期管理系统

我需要为每个员工假期请求为给定的日期范围创建半天

源表: 存储所有请求的请求,每个员工一行

id (bigint-PK)
begin_date (date)
begin_in_afernoon (bool)
end_date (date)
end_in_morning (bool)
UserID (int)
样本数据:

目标表: 缺勤半天

样本数据:

我一直在研究如何为每个员工请求创建循环,以便在半天缺勤表中插入新行


提前感谢

未经个人测试。。但应围绕此表单:

DO
$$
DECLARE
    rec record;
    nbd integer;
BEGIN
   for rec in select begin_date, begin_in_afernoon, end_date, end_in_morning, userid, EXTRACT('days' FROM (end_date - begin_date)) AS nbdays 
                from holidays;
   LOOP
       nbd = record.nbdays;

       IF end_in_morning = 't' THEN
          INSERT INTO Half_day_absence (begin_date, 'AM', 0.5, record.userid);
       END IF;

       IF end_in_afternoon = 't' THEN
          INSERT INTO Half_day_absence (end_date, 'PM', 0.5, record.userid);
       END IF;

       IF end_in_morning = 'f' AND end_in_afternoon = 'f' THEN
          WHILE nbd > 0 LOOP       
              INSERT INTO Half_day_absence (begin_date + '' || nbd || ''days', 'AM', 0.5, record.userid);
              INSERT INTO Half_day_absence (begin_date + '' || nbd || ''days', 'PM', 0.5, record.userid);
              nbd := nbd - 1;
          END LOOP;
       END IF;

       RETURN next;
   END LOOP;
END
$$;
也许你应该做更好的周期测试,但这个想法是围绕着这个公式


希望对您有所帮助。

谢谢您的回复。你的代码给了我一个如何做循环的想法。然而,我找到了另一个不需要循环的解决方案:生成_系列函数。以下是我的sql代码片段,如果它对某人有帮助的话:

select 
row_number () over (order by id), --id of new row in destination table
gs as date,
extract(dow from gs) as day_of_week, --Sunday=0/Saturday=6/Monday to Friday=1 à 5
CASE
    WHEN extract(hour from gs) < 13 THEN 'AM'::varchar
    WHEN extract(hour from gs) >=13 THEN 'PM'::varchar
END As day_period
from
(
    select 
    id,
    CASE
        WHEN begin_in_afternoon=false THEN begin_date::date + interval '1' HOUR --business rule: AM started at 1AM
        WHEN begin_in_afternoon=true THEN begin_date::date + interval '13' HOUR --business rule: PM started at 1PM
    END as begin_date,
    CASE
        WHEN end_in_morning=false THEN end_date::date + interval '13' HOUR --business rule: PM started from 1PM
        WHEN end_in_morning=true THEN end_date::date + interval '1' HOUR --business rule: AM started at 1AM
    END as end_date
    from myTable
) h, 
generate_series(h.begin_date, h.end_date, interval '0.5 day')gs
where extract(dow from gs)not in (0,6); --Sunday and Saturday excluded

然后将此选择发送到插入到。。子句将结果集插入目标表

您好,Hervé,感谢您的回复,我会测试并让您知道。
08/11/2017 01:00:00 | AM | 0.5 | 10 | 1
08/11/2017 13:00:00 | PM | 0.5 | 10 | 1
09/11/2017 01:00:00 | AM | 0.5 | 10 | 1
09/11/2017 13:00:00 | PM | 0.5 | 10 | 1
DO
$$
DECLARE
    rec record;
    nbd integer;
BEGIN
   for rec in select begin_date, begin_in_afernoon, end_date, end_in_morning, userid, EXTRACT('days' FROM (end_date - begin_date)) AS nbdays 
                from holidays;
   LOOP
       nbd = record.nbdays;

       IF end_in_morning = 't' THEN
          INSERT INTO Half_day_absence (begin_date, 'AM', 0.5, record.userid);
       END IF;

       IF end_in_afternoon = 't' THEN
          INSERT INTO Half_day_absence (end_date, 'PM', 0.5, record.userid);
       END IF;

       IF end_in_morning = 'f' AND end_in_afternoon = 'f' THEN
          WHILE nbd > 0 LOOP       
              INSERT INTO Half_day_absence (begin_date + '' || nbd || ''days', 'AM', 0.5, record.userid);
              INSERT INTO Half_day_absence (begin_date + '' || nbd || ''days', 'PM', 0.5, record.userid);
              nbd := nbd - 1;
          END LOOP;
       END IF;

       RETURN next;
   END LOOP;
END
$$;
select 
row_number () over (order by id), --id of new row in destination table
gs as date,
extract(dow from gs) as day_of_week, --Sunday=0/Saturday=6/Monday to Friday=1 à 5
CASE
    WHEN extract(hour from gs) < 13 THEN 'AM'::varchar
    WHEN extract(hour from gs) >=13 THEN 'PM'::varchar
END As day_period
from
(
    select 
    id,
    CASE
        WHEN begin_in_afternoon=false THEN begin_date::date + interval '1' HOUR --business rule: AM started at 1AM
        WHEN begin_in_afternoon=true THEN begin_date::date + interval '13' HOUR --business rule: PM started at 1PM
    END as begin_date,
    CASE
        WHEN end_in_morning=false THEN end_date::date + interval '13' HOUR --business rule: PM started from 1PM
        WHEN end_in_morning=true THEN end_date::date + interval '1' HOUR --business rule: AM started at 1AM
    END as end_date
    from myTable
) h, 
generate_series(h.begin_date, h.end_date, interval '0.5 day')gs
where extract(dow from gs)not in (0,6); --Sunday and Saturday excluded