我正在尝试为给定特定约束的所有个人用户返回第一个创建的记录,并且所有但是第一个创建的记录。我的SQL坏了,但我不能为我的生活弄清楚在哪里/为什么。
我有4个感兴趣的模型:用户,课程,问题和QuestionRecord。
每次用户回答问题时,都会生成一个QuestionRecord。 QuestionRecord与用户,课程和问题是多对一的。 (基数是否正确?每个QuestionRecord只有一个用户,一个课程和一个问题的外键)
在Ruby中:
class QuestionRecord < ActiveRecord::Base
belongs_to :user
belongs_to :course
belongs_to :question
…
end
我想要的是在给定课程和问题的情况下,为每个用户返回第一个问题记录。换句话说,如果Jane和Bill两次回答这个问题,John没有尝试过,而且Pete已经回答了7次,我想要回复3条记录,第一次回答尝试,创建日期,来自Jane,Bill,和皮特。
我可以在代码中执行此操作,但希望在SQL中提高效率。
这就是我所拥有的:
SELECT qr.id
FROM users u
INNER JOIN question_records qr
ON u.id =
(SELECT x.user_id
FROM question_records x
WHERE x.course_id = #{course.id}
AND x.question_id = #{question.id}
AND x.user_id = u.id
ORDER BY created_at ASC
LIMIT 1 )
此查询只运行40分钟左右,并且实际上并没有返回任何内容。我用50个记录的子集运行它,并且有一个奇怪的问题,即所有返回的qr.id结果都是“1”
现在,我希望所有用户的所有记录除之外的第一条记录。我的想法是,从本质上讲,这是同一个查询,除了我想要所有记录,并且我想将返回的索引偏移一个:
SELECT qr.id
FROM users u
INNER JOIN question_records qr
ON u.id =
(SELECT x.user_id
FROM question_records x
WHERE x.course_id = #{course.id}
AND x.question_id = #{question.id}
AND x.user_id = u.id
ORDER BY created_at ASC
OFFSET 1 )
然而,显而易见的是,如果第一个查询不起作用,则第二个查询不会。
有人对此查询有任何指导吗?让它尽可能高效是件好事,所以我可以在[course_id,question_id]或其他任何内容上索引question_records。我也假设我错过了使用“GROUP BY x.user_id”的可能性,但不确定如何在不添加更多口香糖的情况下添加它。
对于记录,我们使用的数据库是MySQL。
答案 0 :(得分:0)
对于第一个,这应该足够了
SELECT qr.id, max(field_1), max(field_2), etc.
FROM users u
INNER JOIN question_records qr
ON u.id = qr.user_id
GROUP BY qr.id
ORDER BY [the field that determines the first question]
对于第二个问题,您有几个选择。 1)只需选择并在应用程序层中抛出第一个。 2)开发一个返回任意范围的查询
选项2被称为每组前n个问题,并且您将限制两端的范围。
答案 1 :(得分:0)
对于#1,如果您的ID值是按顺序发出的:
SELECT MIN(qr.id) AS FirstQRID
FROM users AS u INNER JOIN
question_records AS qr ON qr.user_id = u.id
WHERE (qr.course_id = #{course.id}) AND (qr.question_id = #{questionid})
GROUP BY u.id
然后,对于#2:
SELECT qr.id
FROM questions AS qr2
WHERE (qr2.course_id = #{course.id}) AND (qr2.question_id = #{questionid}) AND
(NOT qr.id = (SELECT MIN(qr.id) AS FirstQRID
FROM users AS u INNER JOIN
question_records AS qr ON qr.user_id = u.id
WHERE (qr.course_id = qr2.course_id) AND (qr.question_id = qr2.quesion_id) AND
(qr.user_id = qr2.user_id)))