加入Access 2016中具有最大价值的行

时间:2018-11-15 14:00:20

标签: sql ms-access

尝试选择Access 2016中的所有学生,并为每个学生加入一个计划。效果很好,但不是选择的最新计划... 如果我仅针对特定的student_id运行子查询,则该查询有效,并且选择了最新计划。

SELECT dbo_Student.*, a.*
FROM dbo_Student LEFT JOIN (SELECT TOP 1 * FROM dbo_Plan ORDER BY Year 
DESC, Version DESC)  AS a ON dbo_Student.ID = a.student_id
WHERE Archived = FALSE
ORDER BY Name;

修改
这是我到目前为止使用C perkins取得的最接近的结果:

SELECT s.*, p.*
FROM dbo_Student s LEFT JOIN
(SELECT p1.* 
 FROM dbo_Plan p1 INNER JOIN 
      (SELECT p2.student_id, MAX(p2.ID) As MaxID
       FROM dbo_Plan p2
       GROUP BY p2.student_id
      ) pAgg
      ON p1.student_id = pAgg.student_id 
         AND p1.ID = pAgg.MaxID
) p
ON s.id = p.student_id
WHERE Archived = FALSE
ORDER BY Name;

这假定最大ID是最新计划(Year DESC,版本DESC)。而且它几乎总是可以工作,但是它不是故障安全的。

3 个答案:

答案 0 :(得分:2)

TOP谓词适用于整个查询,并且原始子查询没有为每个学生正确选择记录。 即使针对特定的student_id运行原始查询,在技术上也无法正常工作。似乎这仅是因为许多Student_id巧合地具有相同的“最近年份”,但却是内部子查询,总是选择单个任意记录,该记录与最近一年进行了排序。该查询的寓意:有效的查询要比仅返回看起来正确的代码还要重要。

以下版本与Access SQL兼容。最里面的 aggregate 子查询获取“每个学生”(GROUP BY p2.student_id)的最新年份。然后,下一个子查询将获取与最近一年匹配的完整计划记录。

SELECT s.*, p.*
FROM dbo_Student s LEFT JOIN
    (SELECT p1.* 
     FROM pdbo_Plan p1 INNER JOIN
          (SELECT p2.student_id, 
                 pAgg2.MaxYear,
                 MAX(pAgg2.version) As MaxVersion
           FROM pdbo_Plan p2 INNER JOIN
                (SELECT p3.student_id, MAX(p3.year) As MaxYear
                 FROM dbo_Plan p3
                 GROUP BY p3.student_id
                ) pAgg2
                ON p2.student_id = pAgg2.student_id 
                   AND p2.year = pAgg2.MaxYear
           GROUP BY p2.student_id, pAgg2.MaxYear
          ) pAgg1
          ON p1.student_id = pAgg1.student_id 
             AND p1.year = pAgg1.MaxYear
             AND p1.version = pAgg1.MaxVersion
    ) p
    ON s.id = p.student_id
WHERE Archived = FALSE
ORDER BY Name;

答案 1 :(得分:2)

鉴于您的原始查询暗示单个VersionsYear)可能有多个ORDER BY Year DESC, Version DESC;我建议如下:

select dbo_student.*, b.*
from
    dbo_student left join
    (
        select a.* from dbo_plan a inner join
        (
            select q.student_id, q.year, max(q.version) as v
            from dbo_plan q inner join
            (
                select p.student_id, max(p.year) as y
                from dbo_plan p
                group by p.student_id
            ) s on q.student_id = s.student_id and q.year = s.y
            group by q.student_id, q.year
        ) t on
        a.student_id = t.student_id and 
        a.year = t.year and
        a.version = t.v
    ) b on dbo_student.id = b.student_id
where 
    archived = false
order by 
    name

最里面的查询获得每个Year的最大Student_ID,然后父查询获得每个Version的{​​{1}}的最大Year,连接原始表,以便可以输出所有字段。

答案 2 :(得分:1)

我想你想要

SELECT s.*, p.*
FROM dbo_Student s LEFT JOIN
     dbo_Plan p
     ON p.student_id = s.id AND
        p.year = (SELECT MAX(p1.year)
                  FROM dbo_Plan p1
                  WHERE p1.student_id = p.student_id
                 )
WHERE Archived = FALSE
ORDER BY Name;