“where”中的 MySql 变量子句问题

发布于 2024-10-21 22:53:20 字数 972 浏览 2 评论 0原文

我有一个带有子查询的查询。子查询返回我需要在 php 中返回的值,该值也用于“where”子句中。我试图弄清楚如何才能不执行子查询两次。 我试图将它的值分配给变量。它在“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 子句中,我放置了与“criteria”列中相同的内容。如果没有 WHERE 子句,它的变量就完全按照我的预期工作。我很困惑 - 没有“哪里”: 在此处输入图像描述

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_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":
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对你再特殊 2024-10-28 22:53:20

WHERE 子句使用执行查询之前存在的变量值。

尝试将相关子查询结果嵌入到它自己的子查询中,然后对其进行过滤。 RDBMS 足够聪明,只处理需要的内容,就好像我编写的子查询从来不存在一样...

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 天。您最好从 CURDATE() 中取出 14 天,因为它只发生一次。

WHERE
  expire = CURDATE() - INTERVAL 14 DAY

编辑:

另外,请注意 RDBMS 实际上非常聪明。您编写的 SQL 并不完全是执行的内容,它会被解析、优化、编译等。它最终会成为传统的顺序代码。这意味着 RDBMS 可以发现您多次编写了相同的子查询,并且知道它只需要执行一次,而不是多次...

例如,这里的两个相同的子查询不会每次执行两次记录。 RDBMS 比这更聪明:) 事实上,它甚至可以知道它只需要执行一次,因为结果不依赖于正在处理的记录。

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

也就是说,使用 sub_queries (例如我原来的答案)可以使代码更易于维护(只需要在一处进行更改)。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文