在SQL中返回“仅第一个”和“除了第一个”之外的记录

时间:2012-08-15 20:24:36

标签: mysql sql

我正在尝试为给定特定约束的所有个人用户返回第一个创建的记录,并且所有是第一个创建的记录。我的SQL坏了,但我不能为我的生活弄清楚在哪里/为什么。

对象模型

我有4个感兴趣的模型:用户,课程,问题和QuestionRecord。

每次用户回答问题时,都会生成一个QuestionRecord。 QuestionRecord与用户,课程和问题是多对一的。 (基数是否正确?每个QuestionRecord只有一个用户,一个课程和一个问题的外键)

在Ruby中:

class QuestionRecord < ActiveRecord::Base

  belongs_to :user
  belongs_to :course
  belongs_to :question
…
end

期望结果#1:第一记录

我想要的是在给定课程和问题的情况下,为每个用户返回第一个问题记录。换句话说,如果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”

期望结果#2:所有第一条记录

现在,我希望所有用户的所有记录之外的第一条记录。我的想法是,从本质上讲,这是同一个查询,除了我想要所有记录,并且我想将返回的索引偏移一个:

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。

2 个答案:

答案 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)))