2015-04-23 2 views
0

Я работаю в базе данных, с таблицей с именем stop_times изготовленном как:Построить SQL запрос «самоприсоединение»

+-------+-------------------+---------+----------+----------+ 
| st_id | trip_id   | stop_id | time  | stop_seq | 
+-------+-------------------+---------+----------+----------+ 
|  1 | 10000872820081804 | 22789 | 17:33:00 |  1 | 
|  2 | 10000872820081804 | 22791 | 17:39:00 |  2 | 
|  3 | 10000872820081804 | 22793 | 17:41:00 |  3 | 
|  4 | 10000872820081805 | 22794 | 17:33:00 |  1 | 
|  5 | 10000872820081805 | 22792 | 17:35:00 |  2 | 
| [...] |  [...]  | [...] | [...] | [...] | 
+-------+-------------------+---------+----------+----------+ 

stop_id может быть связано с кратными trip_id, например:

+-------+------------------+---------+----------+----------+ 
| st_id | trip_id   | stop_id | time  | stop_seq | 
+-------+------------------+---------+----------+----------+ 
| 91447 | 1017694581039141 | 1778 | 17:44:00 |  15 | 
| 91599 | 1017694590917762 | 1778 | 22:40:00 |  20 | 
| 91717 | 1017694610917762 | 1778 | 22:40:00 |  20 | 
| 91773 | 1017694610968899 | 1778 | 16:48:00 |  15 | 
| 91909 | 1017694640917762 | 1778 | 22:40:00 |  20 | 
| [...] |   [...]   |  [...] |   [...] | [...] | 
+-------+------------------+---------+----------+----------+ 

Учитывая stop_id а, мне нужно найти свои сосед (из stop_id B), сосед определяются как:

  • A и B имеют общий trip_id (например, элементы 1, 2 и 3 соответствуют этому условию)
  • stop_seq из B должен быть наименьшим верхней гранью stop_seq А (обычно (+1))

Например, здесь и являются neighboors они совместно используют trip_id (например, , но они на самом деле имеют много других trip_id с) и что stop_seq из является 1, и stop_seq из равно 2 (и 2 = min ({2, 3}) где {2, 3} = {stop_seq s.t. trip_id = 10000872820081804 и stop_seq> 1} < - в upper_bounds набор stop_seq из 22789)

Наконец, мне нужно, чтобы получить время между двумя остановками, которая является вычитание обоих времен, но я предполагаю, что я мог (даже я не знаю, как вычитать время в SQL, я думаю, вы можете добиться этого с помощью некоторых функций SQL.)

И что-то более сложное: от соседей будет много дубликатов (потому что много поездок будут иметь эти 2 остановки в качестве соседей), поэтому мне нужно найти ближайший к данному времени (т. е. вычитание времени остановки минус заданное время минимально и положительно)


Например, если SELECT * FROM stop_times WHERE stop_id = 2045 возвращает это:

+-------+------------------+---------+----------+----------+ 
| st_id | trip_id   | stop_id | time  | stop_seq | 
+-------+------------------+---------+----------+----------+ 
| 91421 | 1017694581039138 | 2045 | 12:01:00 |  21 | 
| 91449 | 1017694581039141 | 2045 | 17:48:00 |  17 | 
| 91511 | 1017694590917740 | 2045 | 10:13:00 |  21 | 
| 91543 | 1017694590917746 | 2045 | 12:43:00 |  21 | 
| 91601 | 1017694590917762 | 2045 | 22:43:00 |  22 | 
+-------+------------------+---------+----------+----------+ 

(я сделал LIMIT 5, но давайте предположим, что он возвращает только что). Тогда, я знаю (при просмотре базы данных), что:

  • Для поездки следующая остановка (в stop_seq = 22 здесь, 22 является наименьшее число>, чем 21, в stop_seq из на поездка) и время поездки 5 минут (12:06 - 12:01, где 12:06 - это время в ряду).
  • Для поездки следующая остановка (в stop_seq = 18) является и время поездки является 1мин.
  • и т.д ..

Допустим, я даю время 12:00, и что есть еще одна поездка, которая идет в то (скажем, в 14:00), я хочу, чтобы запрос, чтобы отобразить только один в 12: 01 (потому что это ближе всего к тому времени, которое я дал).

Например, как и также привести к здесь, однако уже в прошлом, если я дам 12:00 как время, и не так близко от 12: 00 as is (12:01 vs 12:40), поэтому единственная поездка на Я хочу, чтобы запрос возвращался: .

(Кроме того, делать это для каждой остановке было бы возможно, но это будет означать, что дает список поездок, связанных с временем, ведущей к каждому отдельному соседу каждого узла, как:

Node 1 
+--- Neighbour 1 
     +--- Time 
     +--- Other time 
     +--- etc. 
+--- Neighbour 2 
     +--- etc. 
Node 2 
+--- etc. 
etc. 

Но это нужно будет своего рода-в JSon-подобной структуры, которую я действительно не знаю, как достичь в SQL)


Как я могу это сделать?

(я попытался с подзапросов и присоединения, но я немного неудобно с SQL и быстро становятся сложными, и через некоторое время, пытаясь решить эту проблему, я чувствую, что я должен был бы Еогеасп или для заявлений, если с и другие наполнители)

ответ

0

Давайте сосредоточимся только на следующей остановки, а то пред стоп.

Учитывая ваши ограничения, вы можете найти следующую остановки на каждую поездку с помощью:

select st.*, 
     (select st2.st_id 
     from stop_times st2 
     where st2.trip_id = st.trip_id and st2.stop_seq > st.stop_seq 
     order by st2.stop_seq 
     limit 1 
     ) as next_st_id 
from stop_times st; 

Мы можем присоединиться к столу, чтобы получить информацию о следующей остановке, и использовать агрегацию, чтобы получить минимум (и трюк, чтобы получить другую информацию):

select st.stop_id, stn.stop_id as next_stop_id, 
     min(stn.time) as min_time, 
     timestampdiff(second, min(stn.time), st.time) as seconds_diff, 
     substring_index(group_concat(stn.st_id order by stn.time), ',', 1) as next_st_id, 
     substring_index(group_concat(stn.trip_id order by stn.time), ',', 1) as next_trip_id  
from (select st.*, 
      (select st2.st_id 
       from stop_times st2 
       where st2.trip_id = st.trip_id and st2.stop_seq > st.stop_seq 
       order by st2.stop_seq 
       limit 1 
      ) as next_st_id 
     from stop_times st 
    ) st join 
    stop_times stn 
    on stn.st_id = st.next_st_id 
group by st.stop_id, stn.stop_id ; 
+0

Спасибо за ваш ответ. Но 'select st2.st_id from stop_times st2 где st2.trip_id = st.trip_id order by st2.stop_seq limit 1' вернет первую остановку поездки, а не первую верхнюю границу (т.е. следующая остановка в поездке). Я действительно не выполнил запрос tho:? – servabat

+0

Я обновил свой пост, надеясь быть более ясным. – servabat

Смежные вопросы