7 votos

Encontrar viajes similares en una base de datos

Tengo un trips tabla y un bus_stops tabla. El trips tabla tiene un from_stop_id y to_stop_id. El bus_stops tabla tiene lat y lng información para cada parada de autobús.

¿Cómo puedo solicitar los viajes en orden descendente de popularidad, donde popularidad se define como el número de viajes en la base de datos que comienzan y terminan dentro de una determinada distancia del viaje? Por el momento, estoy feliz de trabajar con 'a vuelo de pájaro de la distancia entre dos puntos.

Ninguna de las tablas es espacial, pero yo estoy usando Postgres y la adición de PostGIS extensión, también es posible, así que si esa es la mejor manera de avanzar, a continuación, me encantaría escucharlo.

un millón de gracias

4voto

GriffinHeart Puntos 187

He aquí un enfoque. Primero consigue PostGIS instalado. Hay un montón de explicaciones de cómo hacerlo, tales como postgis.net instalación:

Ahora haga su bus_stops tabla espacial:

-- Assuming the Lng/Lat are WGS84 coordinates 
SELECT AddGeometryColumn('bus_stops','geom',4326,'POINT',2); 

UPDATE bus_stops SET geom=ST_MakePoint(lng, lat);

-- Here's a query that returns the distances for each trip 
-- between the "from' bus_stop and the "from" stop of all the other trips 

SELECT ST_Distance_Sphere(bs1.geom, bs2.geom), t.t_id  
FROM trips AS t, bus_stops AS bs1, bus_stops AS bs2  
WHERE ( t.from_bs_id=bs1.bs_id AND t.from_bs_id <> bs2.bs_id );  

-- And similarly, the distances between the "to" bus stops 

SELECT ST_Distance_Sphere(bs1.geom, bs2.geom), t.t_id  
FROM trips AS t, bus_stops AS bs1, bus_stops AS bs2  
WHERE (t.to_bs_id=bs1.bs_id AND t.to_bs_id<>bs2.bs_id);

-- To count how many trips have "from" stops within a certain minimum:
-- (The numbers are from some fictitious tables)
-- (I choose 3000 m. as a sample. Set to whatever is needed...)  

SELECT t.t_id AS TripID, count(t.t_id) As Cnt_Close 
FROM trips AS t, bus_stops AS bs1, bus_stops AS bs2 
WHERE (t.to_bs_id=bs1.bs_id AND 
    t.to_bs_id<>bs2.bs_id) AND 
    ST_Distance_Sphere(bs1.geom, bs2.geom) < 3000 
GROUP BY TripID ORDER BY Cnt_Close; 
tripid | cnt_close 
            --------+-----------
                  8 |         1
                 11 |         1
                  9 |         1
                 13 |         2
                  7 |         2
                 12 |         2
                 10 |         2
                  5 |         2
                  4 |         2
                  6 |         3
                  1 |         3
                 14 |         3
                  2 |         5
                  3 |         5
            (14 rows)

Por lo tanto, estamos muy cerca de llegar... lo Siguiente que se funden en la consulta tanto de las distancias de las paradas y las distancias a los "a" paradas:

SELECT t.t_id AS TripID, count(t.t_id) As Cnt_Close 
FROM trips AS t, bus_stops AS bs1, bus_stops AS bs2, bus_stops AS bs3, bus_stops AS bs4 
WHERE (t.to_bs_id=bs1.bs_id AND t.to_bs_id<>bs2.bs_id) AND 
    (t.from_bs_id=bs3.bs_id AND t.from_bs_id<>bs4.bs_id) AND 
    ST_Distance_Sphere(bs1.geom, bs2.geom) < 2000 AND 
    ST_Distance_Sphere(bs3.geom, bs4.geom) < 2000 
GROUP BY TripID ORDER BY Cnt_Close;
     tripid | cnt_close 
    --------+-----------
          5 |         2
          8 |         2
          9 |         2
          1 |         2
         11 |         2
          2 |         2
         13 |         3
          3 |         3
          7 |         4
          6 |         4
         10 |         4
         14 |         6
    (12 rows)

Ahora estamos listos para la instalación de la popularidad. En primer lugar añadir una columna para mantener el valor:

ALTER TABLE trips ADD COLUMN popularity INTEGER;
-- Now the update using the above subquery

UPDATE trips SET popularity=(
SELECT count(t.t_id) 
FROM trips AS t, bus_stops AS bs1, bus_stops AS bs2, bus_stops AS bs3, bus_stops AS bs4 
WHERE (t.to_bs_id=bs1.bs_id AND t.to_bs_id<>bs2.bs_id) AND 
    (t.from_bs_id=bs3.bs_id AND t.from_bs_id<>bs4.bs_id) AND 
    ST_Distance_Sphere(bs1.geom, bs2.geom) < 2000 AND 
    ST_Distance_Sphere(bs3.geom, bs4.geom) < 2000 AND 
    t.t_id=trips.t_id
);
UPDATE 14

¡Uf...

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X