2012-04-14 52 views
0

我編寫了一個簡單的Web應用程序,可以讓您在Google地圖上標記跳蚤市場標識。 每個展臺都存儲在一個sqlite3數據庫及其地理位置和其他信息。 這是看臺上表CREATE語句:SQL中的地理位置查詢結果不一致

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錯誤。

回答

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; 

另一種方法是存儲在城市表中的擴大邊界:

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; 

附:我不確定變量語法是否可以在SQLite中使用,但如果不是,只需用@e替換爲0.0000000000001即可。

+0

非常好,非常感謝你,先生! – Jonsku 2012-04-14 12:01:27

+0

不,SET語法不被sqlite支持。我手動修補了數據庫並修改了處理數據庫事務的PHP腳本,以擴大創建和更新的界限。 – Jonsku 2012-04-14 13:10:30

+0

我很高興你的工作。 – 2012-04-14 13:15:29

0

原因是您使用LEFT JOIN,因此它包含所有城市,無論stands表中是否有匹配。請注意0​​如何爲該行返回0

只需使用INNER JOIN而不是LEFT JOIN。這將告訴MySQL只返回符合ON條件的行。

UPD:我誤解了這個問題,所以這個答案是錯誤的。我會發表另一個答案。

+0

謝謝,但INNER JOIN不能解決問題。約恩蘇行的COUNT應該返回1而不是0,因爲在城市範圍內有一個展位(Lat:62.5990455742272 - 62.5990653244875,Long:29.7706540​​507874 - 29.7706540​​507875):** 518892420 | Joensuu - Ilosaari | Siltakatu 1,80100 Joensuu,芬蘭| 62.5990455742272 | 29.7706540​​507875 ** \ n問題處於ON狀態,出於某種原因,展臺不算。 – Jonsku 2012-04-14 11:28:01