Переменная MySql в предложении «где» - PullRequest
0 голосов
/ 15 марта 2011

У меня есть запрос с подзапросом в нем. подзапрос возвращает значение, которое мне нужно вернуть в php и которое также используется в предложении «где». я пытаюсь понять, как я не могу выполнить этот подзапрос два раза. Я пытаюсь присвоить значение этой переменной. И он прекрасно работает в «select», но когда я использую переменную в предложении «where», запрос возвращает 0 строк.

SELECT  t.tour_id, t.tour_name, u.company_name, u.first_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()

В предложении WHERE я поместил то же самое, что и в столбце "критерий". и без предложения WHERE переменная работает именно так, как я ожидаю. Я в замешательстве - без "где" enter image description here

1 Ответ

2 голосов
/ 15 марта 2011

Предложение WHERE использует значение переменной, представленное перед выполнением запроса.

Попробуйте встроить коррелированный результат подзапроса в собственный подзапрос, а затем отфильтровать его. СУБД достаточно умна, чтобы обрабатывать только то, что нужно, как если бы подзапрос, который я написал, вообще не существовал ...

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()

Примечание:

Предложение WHERE включает добавление 14 дней к каждому значению срока годности. Вам может быть лучше взять 14 дней из CURDATE () вместо этого, это происходит только один раз.

WHERE
  expire = CURDATE() - INTERVAL 14 DAY

EDIT:

Также обратите внимание, что СУБД на самом деле довольно умны. SQL, который вы пишете, не совсем то, что выполняется, он анализируется, оптимизируется, компилируется и т. Д. Он заканчивается как традиционный последовательный код. Это означает, что СУБД может обнаружить, что один и тот же подзапрос записан несколько раз, и знать, что его нужно выполнить только один раз, а не несколько раз ...

Например, два идентичных подзапроса здесь не будут выполняться дважды для каждой записи. СУБД умнее этого :) На самом деле, она даже может сказать, что ее нужно выполнить только один раз, потому что результат не зависит от обрабатываемых записей.

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

Тем не менее, использование подзапросов, таких как мой исходный ответ, может упростить поддержку кода (требуется изменение только в одном месте).

...