0

我一直在努力解决我认为简单的 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 个表:resourcesassigned到并且被赋予了该项目projects的特定表。role

此查询的问题在于,它将返回任何资源 + 任何具有“过期”分配 (assignment.enddate < now()) 的资源的数据。但是,我需要将此条件仅应用于该资源的 LAST 分配。你知道我怎么能做到这一点吗?

4

2 回答 2

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()的每个值内的赋值分配一个序号。然后对它们进行排序,以便最新的一个获得值 1 ( )。resource_idpartition by resource_idenddateorder by enddate

于 2013-06-17T11:10:34.997 回答
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和返回的内部连接assignments,但应该适用相同的原则。

编辑

出于某种原因,我认为这是 MySQL,但下面评论中的错误消息看起来更像 Postgresql,在这种情况下,您可以使用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  *, 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;
于 2013-06-17T10:18:26.870 回答