尝试选择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)。而且它几乎总是可以工作,但是它不是故障安全的。
答案 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)
鉴于您的原始查询暗示单个Versions
(Year
)可能有多个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;