我一直在努力解决我认为简单的SQL查询:
SELECT
resource.firstname,
resource.lastname,
resource.fte,
project.name as project_name,
role.name as role_name,
assignment.startdate,
assignment.enddate,
assignment.numberofdaysperweek
FROM
resource
LEFT JOIN assignment ON resource.id = assignment.resource_id AND assignment.enddate < now()
LEFT JOIN project ON project.id = assignment.project_id
LEFT JOIN role ON role.id = assignment.role_id
所以我在此查询中有4个表:resources
为assigned
到projects
,并为该项目提供了特定的role
。
此查询的问题在于它将返回任何资源+任何具有“已过期”赋值的资源(assignment.enddate&lt; now())的数据。但是,我需要将此条件仅应用于该资源的LAST分配。 您是否知道如何实现这一目标?
答案 0 :(得分:2)
大多数数据库都支持row_number()
功能。使用这样的功能,您可以将其处理为:
SELECT
resource.firstname,
resource.lastname,
resource.fte,
project.name as project_name,
role.name as role_name,
assignment.startdate,
assignment.enddate,
assignment.numberofdaysperweek
FROM
resource
LEFT JOIN (select a.*,
row_number() over (partition by resource_id order by enddate) as seqnum
from assignment a
where assignment.enddate < now()
) assignment
ON resource.id = assignment.resource_id AND seqnum = 1
LEFT JOIN project ON project.id = assignment.project_id
LEFT JOIN role ON role.id = assignment.role_id;
row_number()
函数为resource_id
(partition by resource_id
)的每个值中的分配分配一个序号。然后对它们进行排序,以便具有最新enddate
的那个获得值1(order by enddate
)。
答案 1 :(得分:1)
要将您的分配限制为仅限每个资源的最新分配,您需要找到每个resource_id的最新开始日期,并INNER JOIN
返回分配表;
SELECT assignment.*
FROM assignment
INNER JOIN
( SELECT assignment.resource_id,
MAX(assignment.StartDate) AS StartDate
FROM assignment
GROUP BY assignment.resource_id
) MaxAssignment
ON assignment.resource_id = MaxAssignment.resource_id
AND assignment.StartDate = MaxAssignment.StartDate;
由于您只需要LEFT JOIN
,因此您需要将上述全部内容移动到子查询中,并将整个子查询LEFT JOIN
移回主查询:
SELECT resource.firstname,
resource.lastname,
resource.fte,
project.name as project_name,
role.name as role_name,
assignment.startdate,
assignment.enddate,
assignment.numberofdaysperweek
FROM resource
LEFT JOIN
( SELECT assignment.*
FROM assignment
INNER JOIN
( SELECT assignment.resource_id,
MAX(assignment.StartDate) AS StartDate
FROM assignment
GROUP BY assignment.resource_id
) MaxAssignment
ON assignment.resource_id = MaxAssignment.resource_id
AND assignment.StartDate = MaxAssignment.StartDate
) assignment
ON resource.id = assignment.resource_id
AND assignment.enddate < now()
LEFT JOIN project
ON project.id = assignment.project_id
LEFT JOIN role
ON role.id = assignment.role_id;
如果我误解了您对每个资源的“最后”分配的解释,您可能需要修改子查询MaxAssignmen
内的aggergate和内部联接返回assignments
,但同样如此校长应该适用。
修改强>
出于某种原因,我认为这是MySQL,但下面评论中的错误消息看起来更像Postgresql,在这种情况下,您可以使用ROW_NUMBER
将其限制为仅限每个资源的最后一个分配: / p>
SELECT resource.firstname,
resource.lastname,
resource.fte,
project.name as project_name,
role.name as role_name,
assignment.startdate,
assignment.enddate,
assignment.numberofdaysperweek
FROM resource
LEFT JOIN
( SELECT *, ROW_NUMBER() OVER(PARTITION BY ResourceID ORDER BY StartDate DESC) RN
FROM assignment
) assignment
ON resource.id = assignment.resource_id
AND RN = 1
AND assignment.enddate < now()
LEFT JOIN project
ON project.id = assignment.project_id
LEFT JOIN role
ON role.id = assignment.role_id;