这是我们处理的一些调度数据的虚构示例。
这个想法是天真地问这个问题
鉴于一个项目还有N个计划外的剩余小时数,总人数(从事此工作的人数),并假设每个工人将工作8天;该项目需要在最后安排的一天之后的哪些非周末天?
我有一个简化的dim_dates表:
CREATE TABLE dim_dates (
date_actual DATE NOT NULL,
is_weekend BOOLEAN NOT NULL
);
和项目表:
CREATE TABLE projects (
id SERIAL PRIMARY KEY NOT NULL,
last_scheduled_date DATE NOT NULL,
remaining_hours_required INT NOT NULL,
head_count INTEGER NOT NULL
);
因此,鉴于此项目:
INSERT INTO projects (last_scheduled_date, remaining_hours_required, head_count)
VALUES ('2018-01-04', 21, 1);
参加CEIL(remaining_hours_required::decimal / (8 * head_count))
后,我们需要3天的工作时间。日期2018-01-04是星期四,所以我们应该以下面的星期五,星期一和星期二作为结束日期。
要获得接下来的非周末假期,我们可以轻松加入dim_dates:
SELECT p.*, d.*
FROM projects p
INNER JOIN dim_dates d ON (
d.date_actual > p.last_scheduled_date
AND
d.is_weekend IS FALSE
);
哪些人会在非周末的日期后给我们全部。我的难题是如何将此设置过滤为3行。
(必要的)任务描述是:
答案 0 :(得分:1)
WITH dates AS (
SELECT *,
row_number() OVER(ORDER BY date_actual ASC) AS rownum
FROM dim_dates
WHERE date_actual > '2018-01-04'::date
AND is_weekend IS FALSE
), remain_days AS (
SELECT CEIL (remaining_hours_required::decimal / (8 * head_count))
FROM projects p
)
SELECT *
FROM dates
JOIN remain_days
ON rownum <= ceil
答案 1 :(得分:1)
每个项目使用运行总和来保留剩余时间。 并保持这些限制。
在子查询中,它限制了计算出的最大日期。
这样就不会从dim_dates中的每个下一个日期开始计算。
SELECT
id as projectId
, date_actual as weekDay
, row_number()
over (partition by id order by date_actual desc)-1 as daysRemaining
FROM
(
SELECT
p.id, d.date_actual, p.head_count
, p.last_scheduled_date, p.remaining_hours_required
,(p.remaining_hours_required
- sum(8*head_count) over
(partition by p.id order by date_actual)
) as remaining_hours
FROM projects p
JOIN dim_dates d
ON (d.date_actual > p.last_scheduled_date
AND d.date_actual <= p.last_scheduled_date + cast(ceil(((p.remaining_hours_required/5.0)*7.0)/(8*p.head_count))+1 as int)
AND d.is_weekend IS FALSE)
) q
WHERE remaining_hours > (-8*head_count)
ORDER BY id, date_actual;
在SQL小提琴here上进行测试