在SQL中,如何基于表中某个相对位置的其他行中的值来查询行

时间:2013-09-30 12:26:13

标签: sql sqlite nested-query

我有一个数据库,其中包含有"时间" (整数)加上一些其他属性。

E.g。

CREATE TABLE events (time, attr1, attr2);
INSERT INTO events VALUES (1, 'a', 'foo');
INSERT INTO events VALUES (2, 'b', 'bar');
INSERT INTO events VALUES (4, 'a', 'baz');
INSERT INTO events VALUES (9, 'b', 'quux');
INSERT INTO events VALUES (10, 'c', 'foobar');

现在我想做一个有点复杂的查询:我想找到所有具有属性的事件,表中的 next 事件满足某些条件。例如,我可能想要找到满足所有这些条件的所有事件:

  • attr1 ==' a'
  • 下一个事件(由时间字段确定)有attr2 ==' bar'

这应该在时间1返回事件,但不在时间4返回事件。或者更复杂的例子是:找到满足的所有事件

  • attr1 ==' a'
  • 下一个事件 attr1 ==' c' 有attr2 ==' foobar'

这将在时间1和4返回两个事件。

看起来这应该可以通过某种复杂的嵌套选择来实现,但我还没有设法弄清楚如何。

其他说明:

  • 我正在使用sqlite。
  • 事件是不规则间隔的,所以策略涉及计算“下一步”的位置。活动没有成功。
  • 我知道这些查询将在查询优化器上被谋杀,没关系。
  • 我知道如何通过执行多个选择+非SQL逻辑来实现此目的,但我更倾向于使用纯SQL,因为它嵌入在更大的查询生成系统中。我需要能够生成这种形式的查询,与其他约束相结合等等,它不仅仅是我写过一次并完成的单个查询。

2 个答案:

答案 0 :(得分:2)

通过合并ORDER BYLIMIT,您可以在特定时间后找到下一条记录:

SELECT *
FROM events
WHERE time > 1
ORDER BY time
LIMIT 1

通过在子查询中使用它,您可以从 next 记录中查找值。

您的第一个查询可以像这样实现:

SELECT *
FROM events AS e2
WHERE attr1 = 'a'
  AND (SELECT attr2
       FROM events
       WHERE time > e2.time
       ORDER BY time
       LIMIT 1) = 'bar'

您的第二个查询可以像这样实现(附加条件属于子查询的WHERE):

SELECT *
FROM events AS e2
WHERE attr1 = 'a'
  AND (SELECT attr2
       FROM events
       WHERE attr1 = 'c'
         AND time > e2.time
       ORDER BY time
       LIMIT 1) = 'foobar'

使用time列上的索引可以更快地进行子查询查找。

答案 1 :(得分:1)

select * from events a
where exists 
  (
   select * from events c where c.time =
  (select min(b.time) from events b where b.time > a.time)--next_event
   and c.attr2 = 'bar'
  )
and a.attr1 = 'a'

应该是您的第一个查询。它返回时间1.

http://sqlfiddle.com/#!2/63baf/12

第二个可能是:

select * from events a
where exists 
  (
   select * from events c where c.time =
  (select min(b.time) from events b where b.time > a.time and attr1 = 'c')
   and c.attr2 = 'foobar'
  )
and a.attr1 = 'a'

但它会返回时间1和4(与您的预期不同,但这两行都符合您的条件)

http://sqlfiddle.com/#!2/63baf/15

希望这会有所帮助

尼古拉斯