簡體   English   中英

“多個SELECT,INNER JOIN”sql查詢無法正常工作

[英]“Multiple SELECT, INNER JOIN” sql query not working

我在phpMyAdmin中測試了我的sql查詢,它在那里工作。 但是當我復制它並粘貼到我的代碼中時它返回NULL。 我的其他代碼沒有錯誤,因為當我刪除這個SQL查詢時,它完美無缺。 因此,我相信這個查詢存在一些問題。 我花了2天時間才發現問題。 一個重要的是, it works if I remove INNER JOINit works if I remove INNER JOIN 我嘗試使用JOIN和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 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>

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

編輯 - 使用您的代碼,無論如何都不需要子選擇。

像這樣的東西應該這樣做。:-

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

嘗試一些真正的價值觀。 如果它表現不佳,那么我懷疑問題歸結為索引,因此請執行EXPLAIN並發布結果。

您是否使用變量值運行查詢,即查詢中可能存在某些可能包含錯誤值的變量。請查詢查詢絕對正常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM