基于第一次出现的sql动态限制

时间:2017-09-01 17:23:40

标签: mysql sql

假设下表:

user, timestamp, status_code
1, 2017-08-21 09:03:50, 404
2, 2017-08-21 09:03:48, 200
1, 2017-08-21 09:03:45, 404
1, 2017-08-21 09:03:42, 404
1, 2017-08-21 09:03:41, 200
1, 2017-08-21 09:03:40, 404

如何为该用户选择200首次发生的404限制用户的所有条目:

SELECT * FROM tbl WHERE user = 1 ORDER BY timestamp DESC ... ???

预期结果:

user, timestamp, status_code
1, 2017-08-21 09:03:50, 404
1, 2017-08-21 09:03:45, 404
1, 2017-08-21 09:03:42, 404

3 个答案:

答案 0 :(得分:2)

您可以使用相关的子查询来获取此信息。

select * from tbl t1
where timestamp > (select t2.timestamp 
                   from tbl t2 
                   where t1.user_id=t2.user_id and t2.status_code=200
                   order by t2.timestamp
                   limit 1)
and status_code=404

答案 1 :(得分:0)

使用子查询:

SELECT tbl.* FROM tbl, 
    (SELECT user, MIN(timestamp) AS min_ts 
     FROM tbl 
     WHERE status_code = 200 
     GROUP BY user
    ) AS subtable
WHERE status_code = 404 
AND tbl.user = subtable.user 
AND tbl.timestamp > subtable.min_ts
ORDER BY timestamp DESC

http://sqlfiddle.com/#!9/bf725/3

答案 2 :(得分:0)

我将您的查询解释为查找状态为404且时间戳早于同一用户状态为200的任何行的所有行。

我通过颠倒逻辑来考虑这一点:尝试将每个404行连接到状态为200的同一用户的前一行,如果没有找到,那么404行是您要选择的行。如果找不到这样的行,则外连接将使连接行的所有列都为NULL。

select t1.*
from tbl as t1
left outer join tbl as t2
  on t2.status_code = 200
  and t1.user_id = t2.user_id 
  and t1.timestamp > t2.timestamp 
where t1.status_code = 404 
  and t2.user_id is NULL -- i.e. when the outer join finds no match

按顺序对列(status_code,user_id,timestamp)的索引将有助于优化t1的WHERE条件和t2的JOIN条件。

从逻辑上讲,我的回答类似于Vamsi Prabhala的回答,但我的回答是使用连接而不是相关的子查询,因此我应该更容易优化。