2013-11-20 65 views
0

目前,我有以下查询需要较长的时间来执行SQL查询优化:比较相邻行

SELECT * FROM Table t1 
WHERE EXISTS 
(
    SELECT * FROM Table t2 
    WHERE 
    (
     t1.Key = t2.Key - 1 
     AND t1.Foo = 1 
     AND t2.Bar = 0 
    ) 
) 

Key是主键字段。我只比较相邻的行,所以直觉上看,最快的实现方式是比较所有相邻的行,N-1表示。我的查询的工作方式,我认为它可能会比较每行与Table中的每一行,即采取N * N比较。

有没有更好的方法来编写查询?

+0

'有没有更好的方法来编写查询?'不,它是完美的,典型的DBMS不会执行N * N行 - 比较,而是使用某种合并加入。在这种情况下,问题比选择中的解决方案要好d答案,IMO。 – wildplasser

+0

BTW:请使用理智_metasyntactic_名称;无论是富/酒吧或苹果/橙色或'my_table'或其他。但**不要**命名你的表'表'和你的钥匙'钥匙'。你不会将你的孩子命名为“孩子”,是吗? – wildplasser

+0

我的DBMS似乎没有合并连接。布拉德的回答比这个速度快4倍。 – rwolst

回答

2

如何像:

Select t1.* 
From table t1 
inner join table t2 
on t1.key = t2.key - 1 
where t1.Foo = 1 
and t2.Bar = 0 

我在测试这一个表有几百万行,它运行在大约10秒内

+0

这是错误的,因为这也会从t2别名中选择列。 (或者它是一张桌子?)。 (另:从表t1的语法是错误的) – wildplasser

+0

我修正了问题1,我不明白问题2.当然,在某些数据库中,“表”是一个关键字,但似乎这并不妨碍提问者。 – Brad

+0

好吧,看起来OP将他的表格命名为“table”,这相当愚蠢的恕我直言。你会不会给你的孩子命名为“孩子”?顺便说一句:我不认为't1。*'语法是标准的ANSI-SQL,但是它是一些实现使用的扩展。 (我仍然认为'EXISTS(..)'版本更清洁,因为它避免了将外部查询中的t2别名_leaking_) – wildplasser

1

试试这个:

SELECT t1.* FROM Table t1 
LEFT JOIN Table t2 ON (t1.Key = t2.Key-1) 
WHERE t1.Foo=1 AND t2.Bar = 0 

LEFT JOIN基本上过滤掉表B中不存在的行(在这种情况下 - T2)。经验法则是避免子查询,如果它们不是必需的,或者如果您不确定它们将执行得很好(快速)。

另外,还要确保你使用正确的指数化(除了关键,我会做一个索引上对字段:(美孚,酒吧)