SQLite以前在where子句中select的值

序言(你可以跳过这个,这只是我的理由)

我已经创build了一个使用sqlite作为其数据库后端的应用程序,并且该模式在一般的应用程序使用过程中工作(和执行)非常好。

现在我正在尝试为它build立一个报告系统,并且我build立了一个excel xll,它可以从一个未命名的DSN创build查询表。 正因为如此,我只能在sql中完成所有的报告(即,我无法编程)。 除了一个查询之外,这一切都很好

///跳过这里….

我的数据库包含一个特征列表,它具有一个ID,距离和一个指标,以确定这个特征是不是一个标记。 id不一定与距离相同(id为10的特征可能具有距离100,id为11的特征可能具有距离90)。

所以这个项目基本上是这样的:

Feature { int id, int distance, bool is_marker } 

我想要做的是find下一个和以前的function,也是标记。

///编辑

我第一次尝试使用:

 select * /* I want all the data from this feature */ (select MAX(f2.distance) - f1.distance from feature as f2 where f2.is_marker && f2.distance < f1.distance) /* and the distance to the previous marker */ from feature as f2 

第二次尝试(这个工作,它只需要WAAAY太长,10万个function,大约9天左右…):

 select *, /* I want all the data from this feature */ (select f1.distance - MAX(f2.distance) from feature as f2 where f2.distance AND f2.distance< f1.distance) /* and the distance to the previous marker */ from feature as f1 

这个查询不会返回我想要的,并且对小型数据库有足够的性能,但是我也必须支持更大的数据库。

(有些数据库的functionless于1000个,但我现在正在使用的function有90,000多个function,对1000个function的查询需要<1秒,但对于90,000个function的查询需要20个小时,这是因为它没有线性增长导致性能下降80倍:20 * 60 * 60 /(90,000 / 1000)= 8000)

后端数据库使用sqlite,我使用sqliteodbc连接器来连接excel。

如果我在代码中这样做,我会这样做:

 var features = featureRepository.GetAll(); var featuresWithMarkerDistance = new List<FeatureWithMarkerDistance>(); var previousMarker = null; for(var index = 0; index < features.Length; index++) { var currentFeature = features[index]; featuresWithMarkerDistance.Add( new FeaturesWithMarkerDistance(currentFeature, feature.distance - previousMarker.distance)); if(feature.is_marker) { previousMarker = feature; } } // FeatureWithMarkerDistance { int id, int distance, bool is_marker, int marker_distance } 

// EDITS:

这是一个具体的例子:

 (The underlying table) feature_id is_marker distance 1 false 100 2 false 90 3 false 101 4 true 50 5 false 5 6 true 85 7 false 150 8 false 75 

(有一个距离指数)

我想要的结果是:

 feature_id is_marker distance distance_to_closest_previous_marker 1 false 100 15 2 false 90 5 3 false 101 16 4 true 50 null 5 false 5 null 6 true 85 35 7 false 150 65 8 false 75 25 

因此,如果我得到feature_id 1的上一个标记,那么feature_id 1的距离为100,距离85的距离最近的标记为feature_id 6。为了得到最接近的上一个标记的距离,我取(100-85)= 15。我需要得到这个值,每一个function包括在报告中。 (这必须在一个SQL查询中完成,因为我使用的是带有excel的odbc连接器)。 上面的查询确实获取了我想要的内容,但它只是执行得非常糟糕,因为在where子句中它必须在整个数据库中search每个特性。

我想要做的是:(除非有更高性能的方式)

  select * /* I want all the data from this feature */ /* previous = */ (select MAX(f2.distance) - f1.distance from feature as f2 where f2.is_marker && f2.distance >= previous && f2.distance < f1.distance) /* and the distance to the previous marker */ from feature as f2 

所以基本的理论是,我将存储以前的标记值,只有当我正在寻找下一个标记时,才能看到那个值。

原来对于混淆抱歉(我原本忘了放MAX())

我使用SQLite3shell,我试图适应你的查询

 SELECT *, (SELECT MIN(feature.distance-distance) FROM feature AS f WHERE is_marker AND distance<feature.distance) FROM feature; 

5000个logging的performance相当不错。 也许你最薄弱的一点是sqliteobdc? 如果确实还是很慢,并且假设您没有什么is_marker,那么您可以创build一个距离feature_marker为true的特征距离的表格:

 CREATE TEMP TABLE markers_distance (distance); CREATE UNIQUE INDEX markers_idx ON markers_distance (distance); INSERT OR IGNORE INTO markers_distance SELECT distance FROM feature WHERE is_marker; 

现在您对markers_distance的查询应该快得多:

 SELECT *, (SELECT MIN(feature.distance-distance) FROM markers_distance WHERE distance<feature.distance) FROM feature; 

不知道SQLite,但做这样的工作(我查了语法,发现左join和存在,但不是不存在)?

 select f2.*, f2.distance - f1.distance from feature f2 left join feature f1 on f1.is_marker and f2.distance > f1.distance and not exists(select 1 from feature f1b where f1b.is_marker and f2.distance > f1b.distance and f1.distance < f1b.distance) where f2.is_marker 

我不知道性能,但期望(is_marker,距离)上的索引可以是有利的(你必须testing是否是有用的,包括is_marker在索引或不,除了这取决于SQLite,它大概还取决于具有is_marker = true的列的百分比)。

这些例子真的有帮助。 干得好。

 SELECT F2.feature_id, F2.is_marker, F2.distance, F2.distance - (SELECT F1.distance FROM features F1 WHERE F1.is_marker<>0 AND F1.distance<F2.distance ORDER BY F1.distance DESC LIMIT 1) AS "distance_to_closest_previous_marker" FROM features F2