[英]“Multiple SELECT, INNER JOIN” sql query not working
I tested my sql query in phpMyAdmin and it works there. 我在phpMyAdmin中测试了我的sql查询,它在那里工作。 But when I copy it and paste in my code then it return NULL. 但是当我复制它并粘贴到我的代码中时它返回NULL。 My other code is error-free as it works perfect when I remove this sql query. 我的其他代码没有错误,因为当我删除这个SQL查询时,它完美无缺。 Thus, I believe there is some problem with this query. 因此,我相信这个查询存在一些问题。 I spent 2 days to find the problem. 我花了2天时间才发现问题。 One important thing is that it works if I remove INNER JOIN
. 一个重要的是, it works if I remove INNER JOIN
, it works if I remove INNER JOIN
。 I tried using JOIN and FULL JOIN, but none of them works. 我尝试使用JOIN和FULL JOIN,但它们都不起作用。 Does anyone see any problem with this query? 有没有人看到这个查询有任何问题?
Below is my query : 以下是我的查询:
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 . ")))
Thank you. 谢谢。
This is my code : 这是我的代码:
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;
}
The alternate query which runs perfect. 运行完美的备用查询。 But it is not good at performance. 但它在表现上并不擅长。 I want to shift INNER JOIN in outer SELECT. 我想在外部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;";
Query by removing FULL 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 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 Table userTrip表
id | userName<br>
1 | A<br>
2 | B<br>
3 | C<br>
4 | D<br>
5 | E<br>
6 | F<br>
user Table 用户表
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>
You appear to have a random ORDER BY user.id in the middle of your SELECT statement. 您似乎在SELECT语句中间有一个随机的ORDER BY user.id。
EDIT - Playing around with your code, there is no need for a subselect anyway. 编辑 - 使用您的代码,无论如何都不需要子选择。
Something like this should do 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
Try that with some real values. 尝试一些真正的价值观。 If it performs poorly then I suspect the issue is down to indexes, so do an EXPLAIN and post the results. 如果它表现不佳,那么我怀疑问题归结为索引,因此请执行EXPLAIN并发布结果。
您是否使用变量值运行查询,即查询中可能存在某些可能包含错误值的变量。请查询查询绝对正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.