sql >> Databáze >  >> RDS >> Mysql

SQL dotaz na celkový počet bodů v okruhu umístění

MySQL Guru nebo ne, problém je v tom, že pokud nenajdete způsob, jak odfiltrovat různé řádky, je třeba vypočítat vzdálenost mezi každým bodem a každým městem...

Existují dva obecné přístupy, které mohou situaci pomoci

  • zjednodušte vzorec vzdálenosti
  • odfiltrujte nepravděpodobné kandidáty do okruhu 100 000 z daného města

Než se pustíte do těchto dvou cest vylepšení, měli byste se rozhodnout o požadované úrovni přesnosti s ohledem na tuto vzdálenost 100 mil a také byste měli uvést, která geografická oblast je pokryta databází (je to jen kontinentální USA atd.

Důvodem je to, že i když je vzorec Velkého kruhu přesnější numericky, je velmi výpočetně nákladný. Další cestou ke zlepšení výkonu by bylo uložení "souřadnic mřížky" druhů vedle (nebo místo nich) souřadnic Lat/Long.

Upravit :
Několik nápadů na jednodušší (ale méně přesný) vzorec :
Vzhledem k tomu, že máme co do činění s relativně malými vzdálenostmi (a hádám mezi 30 a 48 stupni severní šířky), můžeme použít euklidovskou vzdálenost (nebo ještě lépe druhou mocninu euklidovské vzdálenosti) spíše než složitější vzorce sférické trigonometrie.
v závislosti na očekávané úrovni přesnosti může být dokonce přijatelné mít jeden jediný parametr pro lineární vzdálenost pro celý stupeň zeměpisné délky, přičemž se vezme něco průměrného v uvažované oblasti (řekněme přibližně 46 statut míle). Vzorec by se pak stal

  LatDegInMi = 69.0
  LongDegInMi = 46.0
  DistSquared = ((Lat1 - Lat2) * LatDegInMi) ^2 + ((Long1 - Long2) * LongDegInMi) ^2

Myšlenka sloupců s informacemi o mřížce k filtrování, aby se omezil počet řádků uvažováno pro výpočet vzdálenosti.
Každému "bodu" v systému, ať už je to město, nebo jiný bod (?místa dodání, umístění prodejen... cokoli), jsou přiřazeny dvě celočíselné souřadnice, které definují čtverec řekněme 25 mil * 25 mil, kde leží bod. Souřadnice jakéhokoli bodu do 100 mil od referenčního bodu (daného města) budou maximálně +/- 4 ve směru x a +/- 4 ve směru y. Poté můžeme napsat dotaz podobný následujícímu

SELECT city, state, latitude, longitude, COUNT(*)
FROM zipcodes Z
JOIN points P 
  ON P.GridX IN (
    SELECT GridX - 4, GridX - 3, GridX - 2, GridX - 1, GridX, GridX +1, GridX + 2 GridX + 3, GridX +4
   FROM zipcode ZX WHERE Z.id = ZX.id)
  AND
   P.GridY IN (
    SELECT GridY - 4, GridY - 3, GridY - 2, GridY - 1, GridY, GridY +1, GridY + 2 GridY + 3, GridY +4
   FROM zipcode ZY WHERE Z.id = ZY.id)
WHERE P.Status = A
   AND ((Z.latitude - P.latitude) * LatDegInMi) ^2 
      + ((Z.longitude - P.longitude) * LongDegInMi) ^2 < (100^2)
GROUP BY city,state,latitude,longitude;

Všimněte si, že LongDegInMi může být buď pevně zakódováno (stejné pro všechna místa v rámci kontinentálních USA), nebo pocházet z odpovídajícího záznamu v tabulce PSČ. Podobně lze napevno zakódovat LatDegInMi (není potřeba jej měnit, protože na rozdíl od druhého je relativně konstantní).

Důvodem, proč je to rychlejší, je to, že u většiny záznamů v kartézském součinu mezi tabulkou PSČ a tabulkou bodů vůbec nepočítáme vzdálenost. Eliminujeme je na základě hodnoty indexu (GridX a GridY).

To nás přivádí k otázce, které indexy SQL vyrábět. Určitě můžeme chtít:- GridX + GridY + Stav (v tabulce bodů)- GridY + GridX + stav (možná)- Město + Stát + zeměpisná šířka + zeměpisná délka + GridX + GridY v tabulce PSČ

Alternativou k mřížkám je „svázat“ hranice zeměpisné šířky a délky, které budeme uvažovat na základě zeměpisné šířky a délky daného města. tj. podmínka JOIN se stává rozsahem spíše než IN :

JOIN points P 
  ON    P.latitude > (Z.Latitude - (100 / LatDegInMi)) 
    AND P.latitude < (Z.Latitude + (100 / LatDegInMi)) 
    AND P.longitude > (Z.longitude - (100 / LongDegInMi)) 
    AND P.longitude < (Z.longitude + (100 / LongDegInMi)) 


  1. Operace podobná pivotu MySQL pro získání rozdělení procenta celkových událostí za den podle typu události

  2. Python SQLAlchemy - MySQL server odešel

  3. načítání enwiki-latest-categorylinks.sql do mysql

  4. balíček selhává – nelze najít klientskou knihovnu PostgreSQL (libpq)