I have a query with subquery in it. the subquery returns the value, that i need to return in php and that also is used in "where" clause. i trying to figure out how can i not exequte th subquery two times. I trying to assign the value of it to the variable. And it works fine in "select", but when i use variable in "where" clause, the query returns 0 rows.
SELECT t.tour_id, t.tour_name, u.company_name, u.first_开发者_JAVA技巧name, u.last_name,
@expireDate:= (SELECT DATE_ADD(tour_start_date, INTERVAL (t.tour_duration - 1) DAY)
FROM travelhub_tours_instance
WHERE tour_id = t.tour_id
ORDER BY tour_start_date DESC
LIMIT 1) AS expire,
( @expireDate + INTERVAL 14 DAY ) AS expirediff,
CURDATE() AS now,
( (@expireDate + INTERVAL 14 DAY) = CURDATE() ) AS criteria
FROM travelhub_tours t
JOIN travelhub_users u ON t.operator_id = u.user_id
WHERE (@expireDate + INTERVAL 14 DAY) = CURDATE()
In the WHERE
clause, I put the same as in "criteria" column. and without the WHERE clause it variable work exactly how I expect. I'm confused - without "where":
The WHERE clause is using the variable's value as present before the execution of the query.
Try embedding the correlated sub-query result in a sub-query of it's own, then filtering that. The RDBMS is clever enough to only process what is needed, as if the sub-query I've written didn't ever exist...
SELECT
tour_id, tour_name, company_name, first_name, last_name, expire,
(expire + INTERVAL 14 DAY ) AS expirediff,
CURDATE() AS now,
( (expire + INTERVAL 14 DAY) = CURDATE() ) AS criteria
FROM
(
SELECT
t.tour_id, t.tour_name, u.company_name, u.first_name, u.last_name,
(SELECT DATE_ADD(tour_start_date, INTERVAL (t.tour_duration - 1) DAY)
FROM travelhub_tours_instance
WHERE tour_id = t.tour_id
ORDER BY tour_start_date DESC
LIMIT 1) AS expire
FROM
travelhub_tours t
JOIN
travelhub_users u
ON t.operator_id = u.user_id
)
AS sub_query
WHERE
(expire + INTERVAL 14 DAY) = CURDATE()
Note:
The WHERE clause involves adding 14 days to every expiure value. You may be better off taking 14 days from CURDATE() instead, it only happens once.
WHERE
expire = CURDATE() - INTERVAL 14 DAY
EDIT:
Also, note that RDBMS are actually quite clever. The SQL you write isn't exactly what is executed, it gets parsed, optimised, compiled, etc. It ends up as traditional sequential code. This means that the RDBMS can spot that you have the same sub-query written several times, and know that it needs only execute once, not several times...
For example, the two identical sub_queries here won't get executed twice for every record. The RDBMS is cleverer than that :) In fact, it can even tell that it only needs executing once, ever, because the result is not dependant on the records being processed.
SELECT
(SELECT MAX(event_date) FROM event_table) AS max_event_date,
event_date
FROM
event_table
WHERE
(SELECT MAX(event_date) FROM event_table) - INTERVAL 7 DAY <= event_date
That said, using sub_queries such as my original answer can make code easier to maintain (only need changing in one place).
精彩评论