2014-04-04 14 views
10


mam poniższej tabeli:MySQL kwerendy, aby uzyskać trasę podróży

+--------+----------+---------+---------+--------- 
| From | To |Departure| Arrival | ID | 
+--------+----------+---------+---------+--------- 
| A | B  | 0900 | 0930 | 1 | 
+--------+----------+---------+---------+--------- 
| C | D  | 1000 | 1030 | 2 | 
+--------+----------+---------+---------+--------- 
| B | C  | 1100 | 1130 | 3 | 
+--------+----------+---------+---------+--------- 
| D | E  | 1200 | 1230 | 4 | 
+--------+----------+---------+---------+--------- 
| C | D  | 1300 | 1330 | 5 | 
+--------+----------+---------+---------+--------- 


  • odjazdu/przyjazdu czasu i ID zawsze rosnąco;
  • C_D można znaleźć przed i po B_C.

pragnę iść z do D, więc trasa turystyczna powinna być ID1, ID3, ID5 lub A_B, B_C, C_D.

Każda pomoc jest doceniana.
Dzięki.

+1

myślę, że nie można zrobić z jednej kwerendzie, należy napisać funkcję. – Kasyx

+0

co chcesz w tej tabeli, jak co, ... Nie mogę zrozumieć twojego pytania, "idź od A do D, więc trasa podróży powinna być ID1, ID3, ID5 lub A_B, B_C, C_D. – jmail

+0

Tylko uwaga jak poradzisz sobie z opóźnionym czasem przyjazdu? –

Odpowiedz

0

nie jest to możliwe przy użyciu zapytania MySQL. Można to jednak osiągnąć za pomocą języka programowania, takiego jak php, asp (web), C# (windows) itp.

+1

Proszę również podać przykład. Dziękuję Ci. – sshashank124

+0

jest to możliwe przy użyciu zapytań podrzędnych –

1

Można to rozwiązać w procedurze przechowywanej. Ale algorytm ten będzie prawdopodobnie szybszy, gdy zostanie wykonany w pamięci przez język programowania. Po prostu upewnij się, że masz załadowany kompletny zestaw danych, więc nie będziesz musiał wykonywać zapytania w każdej iteracji.

pseudokod:

to = 'D' 
prev_to = 'A' 
array = array(); 
while (prev_to != 'D') { 
    select arrival, to into prev_arrival, prev_to 
    from table 
    where departure > prev_arrival 
    and from = prev_to; 

    array[] = [arrival => prev_arrival, to => prev_to] 
} 

return array 

Edycja: Myślę, że nie miał nic lepszego do roboty;)

Ta klasa wyszuka wszystkie trasy od A do D pomiędzy danym czas rozpoczęcia i zakończenia. Tak jak aplikacja transportu publicznego. Możesz użyć własnych metod łączenia z bazą danych. (Tylko nie dłużej używać mysql_ * funkcje)

<?php 

class RoutePlanner 
{ 
    /** @var string */ 
    protected $departureTime; 
    /** @var string */ 
    protected $departureLocation; 
    /** @var string */ 
    protected $arrivalTime; 
    /** @var string */ 
    protected $arrivalLocation; 
    /** @var array */ 
    protected $schedule; 
    /** @var mysqli */ 
    protected $db; 

    /** 
    * @param string $departureTime 
    * @param string $departureLocation 
    * @param string $arrivalTime 
    * @param string $arrivalLocation 
    * @throws InvalidArgumentException 
    */ 
    public function __construct($departureTime, $departureLocation, $arrivalTime, $arrivalLocation) 
    { 
     $this->departureTime = $departureTime; 
     $this->departureLocation = $departureLocation; 
     $this->arrivalTime = $arrivalTime; 
     $this->arrivalLocation = $arrivalLocation; 
    } 

    /** 
    * @return array 
    */ 
    public function getRoutes() 
    { 
     $schedule = $this->fetchSchedule(); 
     $routes = $this->searchRoutes($schedule); 
     return $routes; 
    } 

    /** 
    * Search all routes that start and end between given times 
    * @param array $schedule - passing as parameter to ensure the order of execution 
    * @return array 
    */ 
    protected function searchRoutes(array $schedule) 
    { 
     $routes = array(); 

     foreach ($schedule as $i => $row) 
     { 
      if ($row['from'] == $this->departureLocation) 
      { 
       $routes[] = $this->getRoute($schedule, $i); 
      } 
     } 

     return $routes; 
    } 

    /** 
    * Get the route when starting at given point and time 
    * @param $schedule 
    * @param $start 
    * @return array 
    */ 
    protected function getRoute($schedule, $start) 
    { 
     $steps = array(); 

     $from = $this->departureLocation; 
     $time = $this->departureTime; 

     for ($i = $start; $i < count($schedule); $i++) 
     { 
      $row = $schedule[$i]; 
      if ($row['from'] == $from && $row['departure'] > $time) 
      { 
       $steps[] = $row; 
       $from = $row['to']; 
       $time = $row['arrival']; 
      } 
     } 

     return $steps; 
    } 

    /** 
    * @return array 
    */ 
    protected function fetchSchedule() 
    { 
     if (! empty($this->schedule)) 
      return $this->schedule; 

     $sql = "select * from schedule where departure >= ? and arrival <= ?"; 

     $db = $this->getDatabase(); 
     $statement = $db->prepare($sql); 
     $statement->bind_param("ss", $this->departureTime, $this->arrivalTime); 
     $statement->execute(); 
     $result = $statement->get_result(); 

     $this->schedule = $result->fetch_all(MYSQLI_ASSOC); 

     $statement->close(); 
     $result->free(); 

     return $this->schedule; 
    } 

    /** 
    * @return mysqli 
    */ 
    protected function getDatabase() 
    { 
     if (empty($this->db)) 
      $this->db = new mysqli('localhost', 'user', 'pass', 'database'); 

     return $this->db; 
    } 

    public function __destroy() 
    { 
     if (! empty($this->db)) 
      $this->db->close(); 
    } 
} 

wykorzystanie takich jak:

<?php 

$planner = new RoutePlanner('Amsterdam', '0300', 'Berlin', '1030'); 
$routes = $planner->getRoutes(); 
+0

Czy można umieścić przykład w PHP? Dzięki. – user1320951

+0

Zobacz edytowaną odpowiedź – winkbrace

1

Możesz przejechać dołączyć tabelę na siebie, aby każdy krok, a następnie można uruchomić pętli w PHP lub cokolwiek to sprawdza odlotu i przylotu, aby upewnić się, że wyjazd jest po przybyciu poprzedniej podróży:

Więc trzeba będzie pewnego rodzaju logiki warunkowej, ale jest to podstawowa idea SQL:

SELECT a.id,b.id,a.From, a.To, a.Departure,a.Arrival, 
b.From,b.To,b.Departure,b.Arrival 
FROM travel a 
JOIN travel b 
ON a.To = b.From 
WHERE a.From = 'A' 
OR b.To = 'D' 
ORDER BY a.Arrival,a.Departure ASC, 
b.Arrival,b.Departure ASC; 

Jeśli chcesz wykonać całą operację za jednym zamachem, możesz przyłączyć się do stołu po raz trzeci, a następnie użyć WHERE a.From = 'A' AND c.To = 'D', jednak myślę, że byłoby wydajniej po prostu wykonać pojedyncze połączenie, a następnie użyć logika warunkowa w pętli i klauzula WHERE do obliczania podróży.

SQLFiddle

Powiązane problemy