0

私はあなたがグーグルマップ上でフリーマーケットスタンドをマークすることを可能にする簡単なウェブアプリケーションを書きました。各スタンドは、ジオロケーションやその他の情報とともにsqlite3データベースに保存されます。これは、standsテーブルのCREATEステートメントです。

CREATE TABLE stands (
id INTEGER PRIMARY_KEY,
name TEXT,
address TEXT,
u REAL,
v REAL,
);

uとvは、それぞれ緯度と経度です。さらに、スタンドをホストする各都市の名前と地理的境界を格納する都市テーブルがあります。これは、ユーザーが都市間をすばやく移動できるようにするために使用されます。

CREATE TABLE cities
(name TEXT PRIMARY_KEY,
u_min REAL,
u_max REAL,
v_min REAL,
v_max REAL);

新しいスタンドが追加されると、新しい行が都市テーブルに追加されます。スタンドが既知の都市にある場合は、必要に応じて都市の境界のみが更新されます。

ここにいくつかのサンプルスタンドがあります:

592077673|Kierrätystori Rovaniemellä|Urheilukatu 1, 96100 Rovaniemi, Suomi|66.4978306921681|25.7220569153442
1321495145|Kruununhaka|Liisankatu, 00170 Helsinki, Suomi|60.1742596|24.9555782    
571688977|Viikki asukastalo LAVAn edusta|Biologinkatu 5, 00790 Helsinki, Suomi|60.2342312|25.04058
563089951|Hämeentie 156|Hämeentie 156, 00560 Helsinki, Suomi|60.2130467082539|24.9785856067459    
518892420|Joensuu - Ilosaari|Siltakatu 1, 80100 Joensuu, Finland|62.5990455742272|29.7706540507875

および都市:

    Rovaniemi|66.4978306921681|66.4978306921681|25.7220569153442|25.7220569153442
Helsinki|60.1577049447137|60.2556221042622|24.9216988767212|25.0662129772156
Järvenpää|60.4513724|60.4513724|25.0819323000001|25.0819323000001
Joensuu|62.5990455742272|62.5990653244875|29.7706540507874|29.7706540507875
Vantaa|60.2731724937748|60.2731724937748|24.9571491285278|24.9571491285278

私が抱えている問題は、都市ごとのスタンドの数を取得することです。これまで、次のクエリを使用してきました。

SELECT cities.name AS city,
  cities.u_min,
  cities.u_max,
  cities.v_min,
  cities.v_max,
  count(stands.id) AS count
FROM cities
LEFT OUTER JOIN stands
  ON ((stands.u BETWEEN cities.u_min AND cities.u_max)
    AND(stands.v BETWEEN cities.v_min AND cities.v_max))
GROUP BY cities.name;

これは次を返します:

Helsinki|60.1577049447137|60.2556221042622|24.9216988767212|25.0662129772156|9
**Joensuu|62.5990455742272|62.5990653244875|29.7706540507874|29.7706540507875|0**
Järvenpää|60.4513724|60.4513724|25.0819323000001|25.0819323000001|1
Rovaniemi|66.4978306921681|66.4978306921681|25.7220569153442|25.7220569153442|1
Vantaa|60.2731724937748|60.2731724937748|24.9571491285278|24.9571491285278|1

ヨエンスーという名前の都市の境界には1つのスタンドがあるため、これは正しくありません。

518892420|Joensuu - Ilosaari|Siltakatu 1, 80100 Joensuu, Finland|62.5990455742272|29.7706540507875

ただし、次のクエリは期待されるスタンドを返します。

SELECT * FROM stands where u between 62.5990455742272 and 62.5990653244875 and v between 29.7706540507874 and 29.7706540507875;

ここで何が悪いのか本当に理解できません。どんな助けでも大歓迎です。

ちなみに、このデータベースをMysqlにインポートしたところ、同じことが起こるので、これがsqlite3のバグではないかと思います。

4

2 に答える 2

1

これは浮動小数点の精度誤差に関係していると思います。このような問題に対処する方法の1つは、少数を導入して境界に追加し、境界を少し広くすることです。これにより、精度エラーが排除されます。

1つのアプローチは、すべてのクエリの境界を直接広げることです。

SET @e = 0.0000000000001;

SELECT cities.name AS city,
  cities.u_min,
  cities.u_max,
  cities.v_min,
  cities.v_max,
  count(stands.id) AS count
FROM cities
LEFT OUTER JOIN stands
  ON ((stands.u BETWEEN cities.u_min - @e AND cities.u_max + @e)
    AND(stands.v BETWEEN cities.v_min - @e AND cities.v_max + @e))
GROUP BY cities.name;

もう1つのアプローチは、拡大された境界を都市テーブルに格納することです。

SET @e = 0.0000000000001;

UPDATE cities
SET cities.u_min = cities.u_min - @e,
  cities.u_max = cities.u_max + @e,
  cities.v_min = cities.v_min - @e,
  cities.v_max = cities.v_max + @e;

PS変数の構文がSQLiteで機能するかどうかはわかりませんが、機能しない場合は、すべて@eを。に置き換えて0.0000000000001ください。

于 2012-04-14T11:51:55.700 に答える
0

その理由は、を使用するため、テーブルLEFT JOINに一致するものがあるかどうかに関係なく、すべての都市が含まれるためです。その行がどのように返されるかにstands注意してください。COUNT0

INNER JOINの代わりに使用してLEFT JOINください。これにより、MySQLは、の条件ONが満たされた行のみを返すようになります。

UPD:質​​問を誤解したので、この答えは間違っています。別の回答を投稿します。

于 2012-04-14T09:34:57.903 に答える