2013-04-17 40 views
0

我在phpMyAdmin中測試了我的sql查詢並且它在那裏工作。但是當我複製它並粘貼到我的代碼中時,它會返回NULL。我的其他代碼是無錯誤的,因爲當我刪除這個SQL查詢時它工作的很好。因此,我相信這個查詢存在一些問題。我花了2天找到問題。重要的是it works if I remove INNER JOIN。我嘗試使用JOIN和FULL JOIN,但沒有一個能夠工作。有沒有人看到這個查詢有任何問題?「Multiple SELECT,INNER JOIN」sql查詢不起作用

下面是我的查詢:

SELECT * 
    From (
     SELECT userTrip.id,userTrip.fromLat,userTrip.fromLon,userTrip.toLat,userTrip.toLon 
      From userTrip 
       WHERE userTrip.userId != :userId 
       AND userTrip.departureTime > CURDATE() 
       AND ABS(UNIX_TIMESTAMP(userTrip.departureTime) - UNIX_TIMESTAMP(:departureTime)) <= " . DEPARTURETIME_DIFFERENCE_THRESHOLD . " * 60 
       AND userTrip.fromLat Between :fromMinLat AND :fromMaxLat 
       AND userTrip.fromLon Between :fromMinLon AND :fromMaxLon 
     ) AS SourcesNearBy FULL JOIN user ON user.id = SourcesNearBy.userId ORDER BY user.id 
     WHERE toLat Between :toMinLat AND :toMaxLat 
     AND toLon Between :toMinLon AND :toMaxLon 
     AND (user.gender LIKE :matchGender OR :matchGender LIKE 'A') 
     AND (:matchAge = -1 OR (CAST(DATEDIFF(CURDATE(),user.birthdate)/365.25 AS UNSIGNED) Between (:matchAge - " . MAX_AGE_DIFFERENCE . ") AND (:matchAge + " . MAX_AGE_DIFFERENCE . "))) 

謝謝。

這是我的代碼:

public function findMatchesForUser($userId,$tripId) 
    { 
     $sql = "SELECT * from userTrip WHERE tripFinished = 0 AND id = :tripId"; 
     $stmt = $this->dbLink->prepare($sql); 
     $stmt->bindParam(':tripId', $tripId, PDO::PARAM_INT); 

     try 
     { 
      $stmt->execute(); 
      $userTrip = $stmt->fetchObject(); 
     } 
     catch (PDOException $err) 
     { 
      echo $err->getMessage(); 
     } 

     if ($userTrip == null) 
      throw new Frapi_Error('Error Code : 500. Try again.'); 

     // get user's trip length 
     $distanceClass = new Distance(); 
     $userTripLength = $distanceClass->drivingDistance($userTrip->fromLat, $userTrip->fromLon, $userTrip->toLat, $userTrip->toLon); 

     // set up first bounding square 
     $this->setUpBoundingSquare($userTrip->fromLat, $userTrip->fromLon, $userTripLength * SOURCE_DISTANCE_THRESHOLD/100, 1); 
     // set up bounding second square 
     $this->setUpBoundingSquare($userTrip->toLat, $userTrip->toLon, $userTripLength * DESTINATION_DISTANCE_THRESHOLD/100, 0); 

     // perform first phase of algorithm 
     $Candidates = $this->firstPhase($userId,$userTrip); 
    } 


private function firstPhase($userId,$userTrip) 
    { 
     $sql = "SELECT * 
        From (
          SELECT userTrip.id,userTrip.fromLat,userTrip.fromLon,userTrip.toLat,userTrip.toLon 
           From userTrip INNER JOIN user ON userTrip.userId = user.id 
            WHERE userTrip.userId != :userId 
            AND (user.gender LIKE :matchGender OR :matchGender LIKE 'A') 
            AND (:matchAge = -1 OR (CAST(DATEDIFF(CURDATE(),user.birthdate)/365.25 AS UNSIGNED) Between (:matchAge - " . MAX_AGE_DIFFERENCE . ") AND (:matchAge + " . MAX_AGE_DIFFERENCE . "))) 
            AND userTrip.departureTime > '".date('Y-m-d H:i:s')."' 
            AND ABS(UNIX_TIMESTAMP(userTrip.departureTime) - UNIX_TIMESTAMP(:departureTime)) <= " . DEPARTURETIME_DIFFERENCE_THRESHOLD . " * 60 
            AND userTrip.fromLat Between :fromMinLat AND :fromMaxLat 
            AND userTrip.fromLon Between :fromMinLon AND :fromMaxLon 
        ) AS SourcesNearBy 
         WHERE toLat Between :toMinLat AND :toMaxLat 
         AND toLon Between :toMinLon AND :toMaxLon;"; 

     $stmt = $this->dbLink->prepare($sql); 

     // Bind parameters 

     $stmt->bindParam(':fromMinLat', $this->fromMinLat, PDO::PARAM_STR); 
     $stmt->bindParam(':fromMinLon', $this->fromMinLon, PDO::PARAM_STR); 
     $stmt->bindParam(':fromMaxLat', $this->fromMaxLat, PDO::PARAM_STR); 
     $stmt->bindParam(':fromMaxLon', $this->fromMaxLon, PDO::PARAM_STR); 
     $stmt->bindParam(':toMinLat', $this->toMinLat, PDO::PARAM_STR); 
     $stmt->bindParam(':toMinLon', $this->toMinLon, PDO::PARAM_STR); 
     $stmt->bindParam(':toMaxLat', $this->toMaxLat, PDO::PARAM_STR); 
     $stmt->bindParam(':toMaxLon', $this->toMaxLon, PDO::PARAM_STR); 
     $stmt->bindParam(':userId', $userId, PDO::PARAM_INT); 
     $stmt->bindParam(':matchGender', $userTrip->matchGender, PDO::PARAM_STR); 
     $stmt->bindParam(':matchAge', $userTrip->matchAge, PDO::PARAM_INT); 
     $stmt->bindParam(':departureTime', $userTrip->departureTime, PDO::PARAM_STR); 

     try 
     { 
      $stmt->execute(); 
      $Candidates = $stmt->fetchAll(); 
     } 
     catch (PDOException $err) 
     { 
      echo $err->getMessage(); 
     } 
     // If no matchCandidates 
     if ($Candidates == null) 
      throw new Frapi_Error("No match candidates found!"); 

     return $Candidates; 
    } 

它運行完美的備用查詢。但它的表現並不好。我想在外部SELECT中移動INNER JOIN。

$sql = "SELECT * 
        From (
         SELECT userTrip.id,userTrip.fromLat,userTrip.fromLon,userTrip.toLat,userTrip.toLon 
          From userTrip INNER JOIN user ON userTrip.userId = user.id 
           WHERE userTrip.userId != :userId 
            AND (user.gender LIKE :matchGender OR :matchGender LIKE 'A') 
            AND (:matchAge = -1 OR (CAST(DATEDIFF(CURDATE(),user.birthdate)/365.25 AS UNSIGNED) Between (:matchAge - " . MAX_AGE_DIFFERENCE . ") AND (:matchAge + " . MAX_AGE_DIFFERENCE . "))) 
            AND userTrip.departureTime > '".date('Y-m-d H:i:s')."' 
            AND ABS(UNIX_TIMESTAMP(userTrip.departureTime) - UNIX_TIMESTAMP(:departureTime)) <= " . DEPARTURETIME_DIFFERENCE_THRESHOLD . " * 60 
            AND userTrip.fromLat Between :fromMinLat AND :fromMaxLat 
            AND userTrip.fromLon Between :fromMinLon AND :fromMaxLon 
        ) AS SourcesNearBy 
         WHERE toLat Between :toMinLat AND :toMaxLat 
         AND toLon Between :toMinLon AND :toMaxLon;"; 

查詢通過去除FULL JOIN

SELECT * 
    From (
     SELECT userTrip.id,userTrip.fromLat,userTrip.fromLon,userTrip.toLat,userTrip.toLon 
      From userTrip 
       WHERE userTrip.userId != :userId 
       AND userTrip.departureTime > CURDATE() 
       AND ABS(UNIX_TIMESTAMP(userTrip.departureTime) - UNIX_TIMESTAMP(:departureTime)) <= " . DEPARTURETIME_DIFFERENCE_THRESHOLD . " * 60 
       AND userTrip.fromLat Between :fromMinLat AND :fromMaxLat 
       AND userTrip.fromLon Between :fromMinLon AND :fromMaxLon 
     ) AS SourcesNearBy INNER JOIN user ON user.id = SourcesNearBy.userId 
     WHERE toLat Between :toMinLat AND :toMaxLat 
     AND toLon Between :toMinLon AND :toMaxLon 
     AND (user.gender LIKE :matchGender OR :matchGender LIKE 'A') 
     AND (:matchAge = -1 OR (CAST(DATEDIFF(CURDATE(),user.birthdate)/365.25 AS UNSIGNED) Between (:matchAge - " . MAX_AGE_DIFFERENCE . ") AND (:matchAge + " . MAX_AGE_DIFFERENCE . "))) 

userTrip表

id | userName<br> 

1 |  A<br> 
2 |  B<br> 
3 |  C<br> 
4 |  D<br> 
5 |  E<br> 
6 |  F<br> 

表用戶

id | userId | fromLat | fromLon | toLat | toLon | departureTime | matchGender | matchAge<br> 
    5 | 1 | 40.712898 | -74.013199 | 40.728157 | -74.077644 | 2013-04-26 15:56:08 | M | 25<br> 
10 | 2 | 28.520140 | -81.388771 | 28.054642 | -82.469940 | 2013-01-17 10:34:56 | F | 30<br> 
+0

檢查你的mysql日誌,看看你的最終請求。 –

回答

0

有你的變量值即運行查詢,有可能是在查詢的一些變量desired.Rest查詢尋找精絕其中可能包含錯誤值。

+0

是的,我用絕對值運行它。它在phpMyAdmin中工作,但沒有與我的代碼集成後。我也嘗試在我的代碼中使用絕對值。 – Geek

+0

如果可能,你可以發佈你的代碼plz –

+0

我編輯我的問題有我的代碼。 – Geek

2

您似乎在SELECT語句的中間有一個隨機的ORDER BY user.id

編輯 - 玩你的代碼,無論如何不需要子選擇。

像這樣的東西應該做it.:-

SELECT userTrip.id,userTrip.fromLat,userTrip.fromLon,userTrip.toLat,userTrip.toLon 
FROM userTrip 
INNER JOIN user 
ON userTrip.userId = user.id 
WHERE userTrip.userId != :userId 
AND (user.gender LIKE :matchGender OR :matchGender LIKE 'A') 
AND (:matchAge = -1 OR (CAST(DATEDIFF(CURDATE(),user.birthdate)/365.25 AS UNSIGNED) BETWEEN (:matchAge - " . MAX_AGE_DIFFERENCE . ") AND (:matchAge + " . MAX_AGE_DIFFERENCE . "))) 
AND userTrip.departureTime > '".date('Y-m-d H:i:s')."' 
AND ABS(UNIX_TIMESTAMP(userTrip.departureTime) - UNIX_TIMESTAMP(:departureTime)) <= " . DEPARTURETIME_DIFFERENCE_THRESHOLD . " * 60 
AND userTrip.fromLat BETWEEN :fromMinLat AND :fromMaxLat 
AND userTrip.fromLon BETWEEN :fromMinLon AND :fromMaxLon 
AND toLat BETWEEN :toMinLat AND :toMaxLat 
AND toLon BETWEEN :toMinLon AND :toMaxLon 

嘗試與一些真正的價值。如果它表現不佳,那麼我懷疑這個問題歸結爲索引,所以做一個解釋併發布結果。

+0

它甚至在刪除ORDER BY後也不起作用。 – Geek

+0

你現在添加的代碼對我來說看起來很好(你已經擺脫了順序和完全連接)。建議這個問題可能與您正在使用的數據有關。 – Kickstart

+0

如果我使用此查詢的替代方法,則相同的代碼/數據將起作用。 – Geek