プリアンブル (これは飛ばしてもかまいません。これは私の正当な理由です)
データベースのバックエンドとして sqlite を使用するアプリケーションを作成しました。スキーマは、一般的なアプリケーションの使用中に非常にうまく機能 (および実行) します。
今、私はそのためのレポート システムを構築しようとしています。名前のない DSN からクエリ テーブルを作成する Excel xll を構築しました。このため、すべてのレポートを SQL のみで行う必要があります (つまり、プログラムで何もできません)。これは、1 つのクエリを除いてすべてに対して非常にうまく機能します...
/// ここでスキップ....
私のデータベースには、ID、距離、およびフィーチャがマーカーであるかどうかを示すインジケータを持つフィーチャのリストが含まれています。ID は必ずしも距離と同じ順序であるとは限りません (ID 10 のフィーチャの距離は 100 であり、ID 11 のフィーチャの距離は 90 である可能性があります)。
したがって、アイテムは基本的に次のようになります。
Feature { int id, int distance, bool is_marker }
私がやろうとしているのは、マーカーでもある次と前の機能を見つけることです。
/// 編集
私の最初の試みは次を使用しました:
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
2 回目の試行 (これは機能します。100,000 の機能を使用するには WAAAY がかかりすぎます。約 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
このクエリは必要なものを返し、小規模なデータベースでは適切に機能しますが、さらに大規模なデータベースもサポートする必要があります。
(一部のデータベースには 1000 未満のフィーチャがありますが、現在取り組んでいるデータベースには 90,000 を超えるフィーチャがあります。1000 フィーチャのクエリには 1 秒未満かかりますが、90,000 フィーチャのクエリには 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 }
// 編集:
具体的な例を次に示します。
(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 を取得します。レポートに含めるすべての機能について、この値を取得する必要があります。(私は Excel で odbc コネクタを使用しているため、これは単一の SQL クエリで実行する必要があります)。上記のクエリは必要なものを取得しますが、where 句ではすべての機能についてデータベース全体を検索する必要があるため、パフォーマンスが非常に悪くなります。
私がやりたいことはこれです:(よりパフォーマンスの高い方法がない限り)
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() を入れるのを忘れていました)