sql >> データベース >  >> RDS >> Mysql

Mysqlの連続する行の距離(経度、緯度)の合計を計算するためのクエリ

    問題の最初の部分の解決策は次のとおりです...

    DROP TABLE IF EXISTS my_table;
    
    CREATE TABLE my_table
    (id     INT NOT NULL AUTO_INCREMENT PRIMARY KEY
    ,user_name   VARCHAR(12) NOT NULL
    ,date             DATE NOT NULL
    ,LAT        DECIMAL(5,3) NOT NULL
    ,LON DECIMAL (5,2) NOT NULL
    );
    
    INSERT INTO my_table VALUES
    ( 1,'maria','2005-01-01',51.555 ,5.014),
    ( 2,'maria','2005-01-01',51.437 ,5.474),
    ( 3,'peter','2005-02-03',51.437 ,5.474),
    ( 4,'john' ,'2005-02-03',51.858 ,5.864),
    ( 5,'maria','2005-02-04',51.858 ,5.864),
    ( 6,'john' ,'2005-02-03',51.437 ,5.474),
    ( 7,'john' ,'2006-02-04',0      ,0),
    ( 8,'john' ,'2006-02-04',51.858 ,5.864),
    ( 9,'john' ,'2006-02-04',51.858 ,5.864),
    (10,'john' ,'2006-02-04',51.437 ,5.474);
    
    
    SELECT x.user_name
         , x.id from_id
         , MIN(y.id) to_id
      FROM my_table x
      JOIN my_table y
        ON y.user_name = x.user_name
       AND y.id > x.id
     WHERE (y.lat <> 0 AND y.lon <> 0)
       AND (x.lat <> 0 AND x.lon <> 0)
     GROUP 
        BY x.id;
    
    +-----------+---------+-------+
    | user_name | from_id | to_id |
    +-----------+---------+-------+
    | maria     |       1 |     2 |
    | maria     |       2 |     5 |
    | john      |       4 |     6 |
    | john      |       6 |     8 |
    | john      |       8 |     9 |
    | john      |       9 |    10 |
    +-----------+---------+-------+
    

    残りの問題については、次のようなものが機能するはずです。

    データベースにgeo_distance_kmという関数があります。このように見え、毎回半正矢関数を入力する手間が省けます:

    delimiter //
    create DEFINER = CURRENT_USER function geo_distance_km (lat1 double, lon1 double, lat2 double, lon2 double) returns double
     begin
       declare R int DEFAULT 6372.8;
       declare phi1 double;
       declare phi2 double;
       declare d_phi double;
       declare d_lambda double;
       declare a double;
       declare c double;
       declare d double;
       set phi1 = radians(lat1);
       set phi2 = radians(lat2);
       set d_phi = radians(lat2-lat1);
       set d_lambda = radians(lon2-lon1);
       set a = sin(d_phi/2) * sin(d_phi/2) +
             cos(phi1) * cos(phi2) *
             sin(d_lambda/2) * sin(d_lambda/2);
       set c = 2 * atan2(sqrt(a), sqrt(1-a));
       set d = R * c;
       return d;
       end;
    //
    delimiter ;
    

    それを私たちがすでに持っているものと組み合わせることができます...

    SELECT user_name
         , YEAR(date) year
         , COALESCE(SUM(distance),0) total
      FROM 
         ( SELECT a.*
                , b.lat to_lat
                , b.lon to_lon
                , ROUND(geo_distance_km(from_lat,from_lon,b.lat,b.lon),3) distance
             FROM
                ( SELECT x.user_name
                       , x.date
                       , x.id from_id
                       , x.lat from_lat
                       , x.lon from_lon
                       , MIN(y.id) to_id
                    FROM my_table x
                    LEFT
                    JOIN my_table y
                      ON y.user_name = x.user_name
                     AND y.id > x.id
                     AND (y.lat <> 0 OR y.lon <> 0)
                     WHERE (x.lat <> 0 AND x.lon <> 0)
                   GROUP
                      BY x.id
                ) a
             LEFT
             JOIN my_table b
               ON b.id = a.to_id
         ) n
     GROUP
        BY user_name
         , year;
    
    +-----------+------+---------+
    | user_name | year | total   |
    +-----------+------+---------+
    | john      | 2005 | 108.024 |
    | john      | 2006 |  54.012 |
    | maria     | 2005 |  88.464 |
    | peter     | 2005 |   0.000 |
    +-----------+------+---------+
    

    何年にもわたる距離をどのように処理するかはよくわかりませんが、これで目的の距離に近づくことができます。




    1. Rails / Postgresql SQLの違い(日付付き)

    2. MySQLで最も一致する行を見つける(InnoDB)

    3. PostgreSQL-データベースの名前を変更

    4. T-SQLで日付から日を取得する方法