给出一个包含列的响应表:
用户名,LessonNumber,QuestionNumber,响应,得分,时间戳
我如何运行一个查询,返回哪些用户在过去5课中的每个问题首次尝试时得分为90分或更高? “最后5节课”是一个限制条件,而不是一个要求,所以如果他们完全只有1节课,但是他们首先尝试了每个问题,那么它们应该包括在结果中。我们只是不想回顾5课程。
关于数据:用户可能正在上不同的课程。有些用户可能还没有完成五节课(例如可能仅在第三课)。每节课都有不同数量的问题。用户有不同的课程路径,因此他们可能会跳过一些课程编号,甚至不按顺序完成课程。
由于这似乎是将时间上不均匀/不连续的值转换为每用户的统一/连续值的问题,我认为我可以通过几个排名函数调用来解决大部分问题。对于“在过去5课中每次问题的第一次尝试”得分超过90的条件规范也很棘手,因为完成的问题数量是每用户可变的。
作为可能需要发生的事情的起点或暗示,我通过使用“row_number()over(按用户名分区,LessonNumber,按时间戳排序的问题编号)”将时间戳转换为每个问题的“尝试号”。 AttemptNumber”。
我还尝试将LessonNumber从绝对值转换为单个用户的连续排名值。我可以使用“dense_rank()over(按照LessonNumber desc的用户名顺序划分)作为LessonRank”,但是假设订单课程已完成,则与LessonNumber的顺序相对应,但遗憾的是并非总是如此。但是,让我们假设是这种情况,因为我确实有一种通过几个连接产生这样一个数字的方法,所以我可以使用描述的dense_rank变换来选择“最后5个已完成的课程”(即LessonRank< = 5)。
对于> 90条件,我想我可以将分数转换为整数,使得如果> = 90则为“1”,如果< = 0则为“0”。 90.然后,我可以引入类似“按用户名分组(分数)= COUNT(分数)。”的条款,它将仅选择所有分数等于1的用户。
任何解决方案或建议都将不胜感激。
答案 0 :(得分:0)
随机建议:
对于“过去5节课中每个问题的第一次尝试”得分超过90的条件规范也很棘手,因为问题的数量是每用户可变的。
相当于
没有第一次尝试得分< = 90最近的5课程
让我觉得用NOT EXISTS
子查询更容易抓住。
首次尝试与where timestamp = (select min(timestamp) ... )
答案 1 :(得分:0)
您需要首先确定每个用户的前5个课程,使用时间戳来确定课程的优先级,然后您可以按分数进行限制。尝试:
Select username
from table t inner join
(select top 5 username, lessonNumber
from table
order by timestamp desc) l
on t.username = l.username and t.lessonNumber = l.lessonNumber
from table
where score >= 90
答案 2 :(得分:0)
你有点放弃了解决方案:
SELECT DISTINCT Username
FROM Results
WHERE Username NOT in (
SELECT DISTINCT Username
FROM (
SELECT
r.Username,r.LessonNumber, r.QuestionNumber, r.Score, r.Timestamp
, row_number() over (partition by r.Username,r.LessonNumber,r.QuestionNumber order by r.Timestamp) as AttemptNumber
, dense_rank() over (partition by r.Username order by r.LessonNumber desc) AS LessonRank
FROM Results r
) as f
WHERE LessonRank <= 5 and AttemptNumber = 1 and Score < 90
)
关于LessonRank
,我使用了你所描述的内容,因为不清楚如何订购课程:第一次尝试课程的第一次尝试的时间戳?或者任何课程问题第一次尝试的时间戳?或者只是课程问题的任何结果的第一个(或最近的?)时间戳?
最里面的Select
会添加您提供的所有AttemptNumber
和LessonRank
。
下一个Select
仅保留会使用户无法进入最终列表的结果 - 所有在过去5课程中得分不足的首次尝试。我们最终会得到一个用户列表 not 想要在最终结果中显示。
因此,在最外面的Select
,我们可以在排除列表中选择不的所有用户。基本上所有其他用户都回答了任何问题。
再多编辑:
这是一个版本,包括评论中的评论。
SELECT Username
FROM
(
SELECT Username, CASE WHEN Score >= 90 THEN 1 ELSE 0 END AS QuestionScoredWell
FROM (
SELECT
r.Username,r.LessonNumber, r.QuestionNumber, r.Score, r.Timestamp
, row_number() over (partition by r.Username,r.LessonNumber,r.QuestionNumber order by r.Timestamp) as AttemptNumber
, dense_rank() over (partition by r.Username order by r.LessonNumber desc) AS LessonRank
FROM Results r
) as f
WHERE LessonRank <= 5 and AttemptNumber = 1
) as ff
Group BY Username
HAVING MIN(QuestionScoredWell) = 1
我在计算出的Having
值上使用MIN
子句和QuestionScoredWell
表达式。
在比较两个查询的执行计划时,此查询实际上更快。不确定这是否部分是由于我的表中数据行数量较少。