Sql 使用条件获取表的前N行

Sql 使用条件获取表的前N行,sql,postgresql,Sql,Postgresql,这是我们处理的一些调度数据的人为示例 这个想法是天真地问这个问题 假设一个项目有N个剩余的非计划时间,负责人计算在该项目上工作的人数,并假设每个工人将工作8天;本项目需要在最后一个计划日之后的哪些非周末日 我有一个简化的dim_dates表: CREATE TABLE dim_dates ( date_actual DATE NOT NULL, is_weekend BOOLEAN NOT NULL ); 以及项目表: CREATE TABLE projects ( id SERI

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

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

假设一个项目有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);
通过计算CEILREMAIN_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行

因此,必要的任务描述是:

计算完成项目所需的剩余天数 取所有dim_日期,其中is_weekend为假,date_actual高于项目的最后计划日期 这里是一个数据摆弄:


使用一个运行总数来保留每个项目的剩余小时数。 并将其限制在一定范围内

在子查询中,它限制计算的最长日期。 这样它就不会从dim_日期开始计算下一个日期

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 FIDLE上的测试

查看您的FIDLE,您只需计算所需的天数,而不是使用4?@JuanCarlosOropeza我不确定您的意思如果我没有弄错的话,首先必须从dim_日期中获取每一行,并用行号注释,然后继续过滤。虽然我的问题没有提到,正如你可以想象的那样,dim_日期非常大,而且在2018-01-04之后选择所有行需要做大量的工作,但是必须先选择dim_日期中的每一行吗?这有点超出了我的SQL技能,所以我在使用它的同时学习它在做什么。子查询将选择dim_date中的每一行(不包括过滤掉的行),但我不知道是否会发生这种情况。从子查询本身选择*将生成每个dim_date。@EmilAhlbäck我在子查询中为其添加了额外的条件。干杯!聪明的:
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;