我如何 return 仅显示学生按日期收到的最后分数?
How do I return only the last score a student has received by date?
我一直在尝试弄清楚如何收集学生在年度测试中获得的最后分数,但我能够想出的唯一有希望的方法是使用 MAX 函数。一切都出错的地方是当我必须对结果中 returning 的其他字段进行 GROUP BY 时。如果我可以从 GROUP BY 中删除 Studenttestscore_Numscore 字段,我认为它会起作用,但我无法这样做。我如何才能根据 Test_Date?
将此写入 return 数据库中每个学生收到的最后一个分数
我在下面写的方式 returns 每个学生的所有分数都不同。我相信如果它允许我从 GROUP BY 中删除 Studenttestscore_Numscore,它会起作用,但它不会。
现在,因为我必须将它包括在内才能使 MAX 函数起作用,所以我得到了学生在本次年度评估中取得的所有分数,除非它与之前的分数相同。
谢谢
SELECT
ps.students.student_number,
ps.test.name AS test_name,
ps.studenttestscore.numscore AS Studenttestscore_Numscore,
MAX(ps.studenttest.test_date) AS test_date
FROM
ps.studenttestscore
INNER JOIN ps.studenttest ON ps.studenttest.id = ps.studenttestscore.studenttestid
INNER JOIN ps.students ON ps.studenttest.studentid = ps.students.id
INNER JOIN ps.testscore ON ps.studenttestscore.testscoreid = ps.testscore.id
INNER JOIN ps.test ON ps.test.id = ps.testscore.testid
WHERE
ps.test.id = 269
AND ps.testscore.id = 439
GROUP BY
ps.students.student_number,
ps.test.name,
ps.studenttestscore.numscore
我通常喜欢用 row_number()
来处理这样的事情。
我为具有多个记录的数据编写了一个子查询,我试图提取最新的记录,并相应地包含一个 partitioned/ordered 的 rownum,然后在 rownum=1 上加入。不需要分组。
因此对于您的查询,要提取每个 student/test ID 的最新记录,它最终会是:
SELECT
ps.students.student_number,
ps.test.name AS test_name,
ps.studenttestscore.numscore AS Studenttestscore_Numscore,
st.test_date
FROM
ps.studenttestscore
INNER JOIN (
select *, rownum = row_number()over(partition by studentid, testid order by test_date desc)
from ps.studenttest
) st ON st.id = ps.studenttestscore.studenttestid and st.rownum = 1
INNER JOIN ps.students ON st.studentid = ps.students.id
INNER JOIN ps.testscore ON ps.studenttestscore.testscoreid = ps.testscore.id
INNER JOIN ps.test ON ps.test.id = ps.testscore.testid
WHERE
ps.test.id = 269
这是假设 testid
字段在您的 ps.studenttest
table 中可用,因为它需要包含在分区中,但我不知道您的架构,所以您如果不是这样,则必须相应地进行修改。
您可以使用 DENSE_RANK()
分析函数中的 returning 值,其中按 ps.students.student_number
列应用分组,同时按 ps.studenttest.test_date
列,以便选择最新的匹配记录并删除当前的 GROUP BY
子句,例如
SELECT s.student_number,
t.name AS test_name,
sts.numscore AS Studenttestscore_Numscore,
st.test_date,
DENSE_RANK() OVER
(PARTITION BY s.student_number ORDER BY st.test_date DESC) AS rank_latest_first
FROM ps.studenttestscore sts
JOIN ps.studenttest st
ON st.id = sts.studenttestid
JOIN ps.students s
ON st.studentid = s.id
JOIN ps.testscore ts
ON sts.testscoreid = ts.id
JOIN ps.test t
ON t.id = ts.testid
WHERE t.id = 269
AND ts.id = 439
ORDER BY rank_latest_first
FETCH FIRST 1 ROW WITH TIES
其中 WITH TIES
选项提供 return 多行,只要单个学生的最新日期不止一个。
DB 的版本应该是 12c+
以便能够使用 FETCH
子句.
使用MAX(...) KEEP (DENSE_RANK LAST ORDER BY ...)
仅保留一列的最后一个值,然后获取另一列的最大值:
SELECT s.student_number,
MAX(t.name) AS test_name,
MAX(sts.numscore) KEEP (DENSE_RANK LAST ORDER BY st.test_date)
AS Studenttestscore_Numscore,
MAX(st.test_date) AS test_date
FROM ps.studenttestscore sts
INNER JOIN ps.studenttest st ON st.id = sts.studenttestid
INNER JOIN ps.students s ON st.studentid = s.id
INNER JOIN ps.testscore ts ON sts.testscoreid = ts.id
INNER JOIN ps.test t ON t.id = ts.testid
WHERE t.id = 269
AND ts.id = 439
GROUP BY
s.student_number,
t.id
或使用 ROW_NUMBER
分析函数对每个分区的行进行排序,然后过滤以仅获取最新的行:
SELECT student_number,
name AS test_name,
numscore AS Studenttestscore_Numscore,
test_date
FROM (
SELECT s.student_number,
t.name,
sts.numscore,
st.test_date,
ROW_NUMBER() OVER (
PARTITION BY s.student_number, t.id
ORDER BY st.test_date DESC
) AS rn
FROM ps.studenttestscore sts
INNER JOIN ps.studenttest st ON st.id = sts.studenttestid
INNER JOIN ps.students s ON st.studentid = s.id
INNER JOIN ps.testscore ts ON sts.testscoreid = ts.id
INNER JOIN ps.test t ON t.id = ts.testid
WHERE t.id = 269
AND ts.id = 439
)
WHERE rn = 1;
我一直在尝试弄清楚如何收集学生在年度测试中获得的最后分数,但我能够想出的唯一有希望的方法是使用 MAX 函数。一切都出错的地方是当我必须对结果中 returning 的其他字段进行 GROUP BY 时。如果我可以从 GROUP BY 中删除 Studenttestscore_Numscore 字段,我认为它会起作用,但我无法这样做。我如何才能根据 Test_Date?
将此写入 return 数据库中每个学生收到的最后一个分数我在下面写的方式 returns 每个学生的所有分数都不同。我相信如果它允许我从 GROUP BY 中删除 Studenttestscore_Numscore,它会起作用,但它不会。
现在,因为我必须将它包括在内才能使 MAX 函数起作用,所以我得到了学生在本次年度评估中取得的所有分数,除非它与之前的分数相同。
谢谢
SELECT
ps.students.student_number,
ps.test.name AS test_name,
ps.studenttestscore.numscore AS Studenttestscore_Numscore,
MAX(ps.studenttest.test_date) AS test_date
FROM
ps.studenttestscore
INNER JOIN ps.studenttest ON ps.studenttest.id = ps.studenttestscore.studenttestid
INNER JOIN ps.students ON ps.studenttest.studentid = ps.students.id
INNER JOIN ps.testscore ON ps.studenttestscore.testscoreid = ps.testscore.id
INNER JOIN ps.test ON ps.test.id = ps.testscore.testid
WHERE
ps.test.id = 269
AND ps.testscore.id = 439
GROUP BY
ps.students.student_number,
ps.test.name,
ps.studenttestscore.numscore
我通常喜欢用 row_number()
来处理这样的事情。
我为具有多个记录的数据编写了一个子查询,我试图提取最新的记录,并相应地包含一个 partitioned/ordered 的 rownum,然后在 rownum=1 上加入。不需要分组。
因此对于您的查询,要提取每个 student/test ID 的最新记录,它最终会是:
SELECT
ps.students.student_number,
ps.test.name AS test_name,
ps.studenttestscore.numscore AS Studenttestscore_Numscore,
st.test_date
FROM
ps.studenttestscore
INNER JOIN (
select *, rownum = row_number()over(partition by studentid, testid order by test_date desc)
from ps.studenttest
) st ON st.id = ps.studenttestscore.studenttestid and st.rownum = 1
INNER JOIN ps.students ON st.studentid = ps.students.id
INNER JOIN ps.testscore ON ps.studenttestscore.testscoreid = ps.testscore.id
INNER JOIN ps.test ON ps.test.id = ps.testscore.testid
WHERE
ps.test.id = 269
这是假设 testid
字段在您的 ps.studenttest
table 中可用,因为它需要包含在分区中,但我不知道您的架构,所以您如果不是这样,则必须相应地进行修改。
您可以使用 DENSE_RANK()
分析函数中的 returning 值,其中按 ps.students.student_number
列应用分组,同时按 ps.studenttest.test_date
列,以便选择最新的匹配记录并删除当前的 GROUP BY
子句,例如
SELECT s.student_number,
t.name AS test_name,
sts.numscore AS Studenttestscore_Numscore,
st.test_date,
DENSE_RANK() OVER
(PARTITION BY s.student_number ORDER BY st.test_date DESC) AS rank_latest_first
FROM ps.studenttestscore sts
JOIN ps.studenttest st
ON st.id = sts.studenttestid
JOIN ps.students s
ON st.studentid = s.id
JOIN ps.testscore ts
ON sts.testscoreid = ts.id
JOIN ps.test t
ON t.id = ts.testid
WHERE t.id = 269
AND ts.id = 439
ORDER BY rank_latest_first
FETCH FIRST 1 ROW WITH TIES
其中 WITH TIES
选项提供 return 多行,只要单个学生的最新日期不止一个。
DB 的版本应该是 12c+
以便能够使用 FETCH
子句.
使用MAX(...) KEEP (DENSE_RANK LAST ORDER BY ...)
仅保留一列的最后一个值,然后获取另一列的最大值:
SELECT s.student_number,
MAX(t.name) AS test_name,
MAX(sts.numscore) KEEP (DENSE_RANK LAST ORDER BY st.test_date)
AS Studenttestscore_Numscore,
MAX(st.test_date) AS test_date
FROM ps.studenttestscore sts
INNER JOIN ps.studenttest st ON st.id = sts.studenttestid
INNER JOIN ps.students s ON st.studentid = s.id
INNER JOIN ps.testscore ts ON sts.testscoreid = ts.id
INNER JOIN ps.test t ON t.id = ts.testid
WHERE t.id = 269
AND ts.id = 439
GROUP BY
s.student_number,
t.id
或使用 ROW_NUMBER
分析函数对每个分区的行进行排序,然后过滤以仅获取最新的行:
SELECT student_number,
name AS test_name,
numscore AS Studenttestscore_Numscore,
test_date
FROM (
SELECT s.student_number,
t.name,
sts.numscore,
st.test_date,
ROW_NUMBER() OVER (
PARTITION BY s.student_number, t.id
ORDER BY st.test_date DESC
) AS rn
FROM ps.studenttestscore sts
INNER JOIN ps.studenttest st ON st.id = sts.studenttestid
INNER JOIN ps.students s ON st.studentid = s.id
INNER JOIN ps.testscore ts ON sts.testscoreid = ts.id
INNER JOIN ps.test t ON t.id = ts.testid
WHERE t.id = 269
AND ts.id = 439
)
WHERE rn = 1;