首頁  >  問答  >  主體

從一大組座標中選擇一些看起來均勻分佈在該區域的座標

我有一個包含區域和緯度/經度位置列的 MySQL 表。每個區域都有許多位置,例如20.000。有沒有辦法只選幾個,像是 100,看起來在地圖上分佈得比較均勻?

分佈不一定要完美,查詢速度更重要。如果直接使用 MySQL 無法做到這一點,則可以使用非常快速的演算法來選擇均勻分佈的位置。

提前致謝。

編輯:回答評論中的一些請求。資料沒有任何可以使用的東西,它只是面積和位置座標,例如:

+-------+--------------+----------+-----------+------------+--------+--------+
| id    | area         | postcode | lat       | lon        | colour | size   |
+-------+--------------+----------+-----------+------------+--------+--------+
| 16895 | Athens       |    10431 | 37.983917 | 23.7293599 | red    | big    |
| 16995 | Athens       |    11523 | 37.883917 | 23.8293599 | green  | medium |
| 16996 | Athens       |    10432 | 37.783917 | 23.7293599 | yellow | small  |
| 17000 | Thessaloniki |    54453 | 40.783917 | 22.7293599 | green  | small  |
+-------+--------------+----------+-----------+------------+--------+--------+

還有一些具有特徵的列,但這些列僅用於過濾。

我確實嘗試同時獲取 nth 行,它似乎可以工作,儘管有點慢

SET @a = 0;
select * from `locations` where (@a := @a + 1) % 200 = 0

使用 random() 也可以,但也有點慢。

編輯2:事實證明,在表格上新增郵遞區號很容易。有了這個,按郵遞區號分組似乎給出了一個賞心悅目的結果。唯一的問題是,有非常大的區域,大約有 3000 個不同的郵政編碼,而僅獲取 100 個可能最終會導致其中許多顯示在一個地方,因此可能需要在 PHP 中進一步處理。

Edit3,在評論中回答@RickJames 的問題,以便它們位於一個位置:

  1. 請定義「均勻分佈」-緯度均勻分佈?沒有兩個人彼此「親近」嗎? ETC。
    • 「均勻分佈」這個字選得不好。我們只是想顯示該區域中的一些位置,但這些位置並非全部集中在一個地方
  2. 「區域」是矩形嗎?六邊形?還是不公平地劃分選區?
    • 它們可以大致被認為是矩形,但這並不重要。我錯過了重要的事情,我們還需要顯示多個區域的位置。區域可能彼此相距較遠或相鄰(但不重疊)。在這種情況下,我們希望將 100 個樣本分配到各個區域。
  3. 「每個區域 100 個」是否固定?或者可以是“大約100”
    • 它不是固定的,大約是 100,但如果它看起來不太好,我們可以更改它
  4. 表上是否有 AUTO_INCRMENT id?數字上有差距嗎?
    • 是的,有一個 AUTO_INCRMENT id 並且可以有間隙
  5. 問題是否從「每個地區 100 個」更改為「每個郵遞區號 1 個」?
    • 不,問題仍然是一樣的,“每個區域顯示 100 個,但並非所有區域都在同一個位置”,如何完成並不重要
  6. 輸出中的總行數和所需的行數是多少?
    • 總行數取決於區域和標準,一個區域最多可達 40k。如果總數超過 1000,我們希望只顯示隨機的 100。如果 1000 或更少,我們可以只顯示所有內容
  7. 每次執行查詢時是否都需要不同的範例?
    • 相同的樣本或不同的樣本(即使具有相同的標準)都可以
  8. 您願意在表格中新增一列嗎?
    • 這不取決於我,但如果我有充分的論點,那麼我們很可能可以添加一個新列

P粉262113569P粉262113569207 天前313

全部回覆(1)我來回復

  • P粉982054449

    P粉9820544492024-02-27 00:20:37

    這是一種可以滿足目標的方法。

    1. 對表格進行預處理,建立一個新表格,以刪除「重複」的項目。
    2. 如果新表足夠小,對其進行完整掃描可能會足夠快。

    至於“重複項”,請將此視為發現兩個項目落在同一位置的粗略方法:

    SELECT ROUND(latitude * 5),
             ROUND(longitude * 3),
             MIN(id) AS id_to_keep
         FROM tbl
         GROUP BY 1,2

    “5”和“3”可以向上(或向下)調整,以保留更多(或更少)的 id。由於緯度/經度的排列方式,「5」和「3」是不同的;這個比例可能適用於大多數溫帶地區。 (在赤道附近使用相同的數量,在更高緯度使用更大的配給。)

    有一個小缺陷...兩個非常接近的項目可能會跨越由 ROUNDs 創建的邊界。

    原表有多少行?上述查詢產生了多少行? ( SELECT COUNT(*) FROM ( ... ) x; )

    回覆
    0
  • 取消回覆