2009-12-17 37 views
0

对于标题感到抱歉,我不确定如何描述这一点,这使得搜索解决方案变得更加困难。mysql查询:选择最新的地方,其他行不存在

我有有许多答案表:

CREATE TABLE `answers` (
    `a_id` int(11) NOT NULL auto_increment, 
    `p_id` int(11) NOT NULL default '0', 
    `q_id` int(11) NOT NULL default '0', 
    `user_id` int(11) NOT NULL default '0', 
    `correct` int(1) NOT NULL default '0', 
    `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`a_id`) 
) ; 

我需要从一个特定的user_idp_id其中正确= 0 q_id,但只有在更近的行从同一USER_ID和的p_id的correct字段不是1

我可以按ID,但我不确定如何消除组,其中顶部正确!= 0

在此先感谢。我在这里找到了很多有用的答案,并期待着尽我所能提供帮助。

编辑:目前查询的看台上,但需要6秒来执行:

无论从你的答案我有查询工作,但需要6秒来执行!

SELECT a.q_id FROM answers a  
JOIN (SELECT b.q_id, MAX(b.a_id) as a_id, b.correct 
     FROM answers b 
     WHERE b.correct = 1 
     AND b.user_id = 1 
     AND b.p_id = 22 
    GROUP BY b.q_id) c ON a.q_id = c.q_id 
         AND a.a_id > c.a_id 
WHERE a.correct = 0 
    AND a.user_id = 1 
    AND a.p_id = 22 
LIMIT 1 

没有加入他们需要.26秒。和.45秒执行我怎样才能使它更有效率?

是否有另一种方法来选择最近的正确= 0行prev correct = 1行不存在?

感谢您的帮助!

+0

看看我的答案,让我知道如果解决。 – Nirmal

+0

@robr:那正确!= 1 /正确!= 0条件,以及这些记录之间的时间戳关系...... –

+0

旧的行是否可以更新,并且假定它是最近的行? – Nirmal

回答

0

此查询似乎工作得最好。这是我编辑的答案,更新了订购a.a_id并将返回限制为一个。

SELECT a.q_id 
     FROM user_q_answers a  
     JOIN (SELECT b.user_id, 
        b.popling_id, 
      b.q_id, 
        MAX(b.a_id) as a_id 
       FROM user_q_answers b 
      WHERE b.correct = 1 
      GROUP BY b.q_id, b.user_id) c ON a.q_id = c.q_id 
             AND a.user_id = c.user_id 
             AND a.a_id > c.a_id 
    WHERE a.correct = 0 
     AND a.user_id = 101 
     AND a.popling_id = 170 
    ORDER BY a.a_id DESC 
    LIMIT 1 

非常感谢OMG Ponies和Nirmal帮助我完成这一切。对不起,如果回答我自己的问题在这里是不好的形式,但我包括我的查询,基于我从你那里学到了什么。

再次感谢!

0

使用时间戳信息获取最新的。您可以根据时间订购记录。

0

由于您有一个自动增加字段a_id,您可以使用它来查找最新条目。时间戳计算比主键排序慢。

SELECT a.a_id, a.q_id, a.user_id, a.p_id, a.correct, c.correct 
    FROM answers a 
    JOIN (SELECT b.p_id, b.user_id, b.correct 
       FROM answers b 
       ORDER BY a_id DESC 
       LIMIT 1) c 
     ON (a.p_id = c.p_id 
     AND a.user_id = c.user_id) 
    WHERE c.correct != '1' 
    AND a.correct = '0' 
    AND a.user_id = '1234' 
    AND a.p_id = '5678' 
    ORDER BY a.a_id DESC 
    LIMIT 1; 

如果您不想限制结果的数量,请删除最后两行代码。

+0

如果我想指定user_id和p_id作为硬编码值,那么这些会跟在a.correct ='0'行之后,那么加入的查询会引用它们?它也看起来像ike ORDER BY a_id DESC需要一个别名:b.a_id。我仍然得到错误'每个派生表都必须有它自己的别名'谢谢你的帮助! – robr

+0

看起来我错过了select语句中的很多列和派生表的别名。我纠正了我的答案。你可以试着让我知道。 – Nirmal

+0

是的。你必须在'a.correct ='0''后面指定它们。我在我的回答中添加了。你可以检查它们。 – Nirmal

0

这是我几乎总是在这些情况下使用的方法。它符合ANSI标准,在MS SQL Server中,性能通常比使用子查询要好得多。顺便说一句,如果你想“最新”,那么你应该看的时间戳,而不是A_ID

SELECT 
    A1.q_id 
FROM 
    Answers A1 
LEFT OUTER JOIN Answers A2 ON 
    A2.p_id = A1.p_id AND 
    A2.user_id = A1.user_id AND 
    A2.timestamp > A1.timestamp AND 
    A2.correct = 1 
WHERE 
    A1.p_id = 22 AND 
    A1.user_id = 1 AND 
    A1.correct = 0 
    A2.a_id IS NULL -- This can only happen if no rows were found matching the JOIN criteria 

,我无法表现在MySQL虽然说话。虽然它可能几乎总是如此(至少插入时),这些数字是基于插入时间而连续的,但通常不能保证。这在MS SQL中绝对是这种情况,并且我很确定在MySQL中也是如此,因为交易和可能的回滚会影响ID。

+0

谢谢Tom H.我会进一步研究这个查询和时间戳问题。我是通过自动增量来订购的,因为它的评论速度比时间戳更快。 – robr

相关问题