首页 > 解决方案 > 使用条件取表的前 N ​​行

问题描述

这是我们处理的一些调度数据的人为示例。

这个想法是天真地问这个问题

假设一个项目还有 N 个剩余的计划外小时数,一个 head_count(从事该项目的人数),并且假设每个工人将工作 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 行。

所以(必要的)任务描述是:

  1. 计算完成项目所需的剩余天数
  2. 取所有 dim_dates 其中 is_weekend 为 false 并且 date_actual 高于项目最后计划日期的日期

这是一个数据:http ://sqlfiddle.com/#!17/f6a90/3

标签: sqlpostgresql

解决方案


SQL 演示

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 

推荐阅读