【问题标题】:MySQL queries and intervalsMySQL 查询和间隔
【发布时间】:2011-02-28 08:36:22
【问题描述】:

这是我做过的最难的查询: http://robertr.pastebin.com/X4bG4pFp

"SELECT  `user`.`id` ,  `user`.`fname` ,  `user`.`lname` , 
YEAR(  `user`.`bday` ) AS  `bday_year` ,  `user`.`class_id` , 
( SELECT  `class`.`class_name` 
  FROM  `wp_class_classes`  `class` 
  WHERE  `user`.`class_id` =  `class`.`id`) AS  `class_name` 
FROM  `wp_class_users`  `user` 
WHERE MONTH(  `bday` ) = $month AND DAY(  `bday` ) = $day 
OR  `user`.`fname` = 
( SELECT  `name`.`names` 
  FROM  `wp_class_namedays`  `name` 
  WHERE  `name`.`day` =  '$month.$day'
  AND  `user`.`fname` =  `name`.`names` )

此查询从三个不同的数据库表中获取数据,以检查数据库中是否有人今天参加了聚会。在拉脱维亚,我们也有 Name Days。无论如何,这个查询运行良好,并且它的工作做得很好,但现在我想让它更酷一点。

我想让它显示下周谁将举办派对。您可能已经注意到 Facebook 每个周末都会向您发送这些电子邮件,显示谁的生日即将到来。

但我就是不明白如何获得至少那个间隔?

我记得 PHP 有一些很好的函数,你可以通过这些函数找到月份的哪一天开始等等,但也许这里有一些光明的心,愿意帮我把我踢得更快一点。

【问题讨论】:

  • 请在此处发布您的相关代码,而不是其他地方,SO 用于显示代码。

标签: php sql date intervals


【解决方案1】:
SELECT
  `user`.`id`,
  `user`.`fname`,
  `user`.`lname` ,
  YEAR(`user`.`bday`) AS  `bday_year`,
  `user`.`class_id`,
  (
    SELECT
      `class`.`class_name`
    FROM  `wp_class_classes`  `class`
    WHERE  `user`.`class_id` =  `class`.`id`
  ) AS  `class_name`,
  CASE
    WHEN MONTH(`week`.`Date`) = MONTH(`user`.`bday`) AND
         DAY(`week`.`Date`) = DAY(`user`.`bday`) THEN 1
    ELSE 2
  END AS `event_type`
FROM  `wp_class_users`  `user`
  LEFT JOIN  `wp_class_namedays`  `name` ON  `user`.`fname` =  `name`.`names`
  LEFT JOIN  (
    SELECT CURDATE() + INTERVAL (1 - DAYOFWEEK(CURDATE())) DAY AS `Date`  UNION ALL
    SELECT CURDATE() + INTERVAL (2 - DAYOFWEEK(CURDATE())) DAY  UNION ALL
    SELECT CURDATE() + INTERVAL (3 - DAYOFWEEK(CURDATE())) DAY  UNION ALL
    SELECT CURDATE() + INTERVAL (4 - DAYOFWEEK(CURDATE())) DAY  UNION ALL
    SELECT CURDATE() + INTERVAL (5 - DAYOFWEEK(CURDATE())) DAY  UNION ALL
    SELECT CURDATE() + INTERVAL (6 - DAYOFWEEK(CURDATE())) DAY  UNION ALL
    SELECT CURDATE() + INTERVAL (7 - DAYOFWEEK(CURDATE())) DAY
  ) `week`
    ON CONCAT(MONTH(`week`.`Date`), '.', DAY(`week`.`Date`)) IN (
      CONCAT(MONTH(`user`.`bday`), '.', DAY(`user`.`bday`)),
      `name`.`day`
    )
WHERE `week`.`Date` IS NOT NULL

用户表与名称日表连接,然后将结果集与当前周的日期进行比较。最终结果集仅列出生日或姓名日期在一周内的用户。

如果您想了解下周的事件,您可以简单地将week.Date 定义中的间隔更改为8 - DAYOFWEEK...9 - DAYOFWEEK... 等。

最后一件事是,您可以使用INNER JOIN 代替选择列表中的相关子查询,如下所示:

SELECT
  `user`.`id`,
  `user`.`fname`,
  `user`.`lname` ,
  YEAR(`user`.`bday`) AS  `bday_year`,
  `user`.`class_id`,
  `class`.`class_name`
FROM  `wp_class_users`  `user`
  INNER JOIN  `wp_class_classes`  `class` ON  `user`.`class_id` =  `class`.`id`
  LEFT JOIN  `wp_class_namedays`  `name` ON  ...  /* the rest of the above script */

上面定义的event_type 列可以告诉您该事件是否是生日,但它不会让您知道该特定人是否既是生日又是命名日。

如果您希望有这种区别,您可以像这样更改event_type 定义:

CASE
  WHEN MONTH(`week`.`Date`) = MONTH(`user`.`bday`) AND
       DAY(`week`.`Date`) = DAY(`user`.`bday`) THEN 1
  ELSE 0
END +
CASE CONCAT(MONTH(`week`.`Date`), '.', DAY(`week`.`Date`))
  WHEN `name`.`day` THEN 2
  ELSE 0
END AS `event_type`

现在列的结果是:

  • 1 – 生日
  • 2 – 命名日
  • 3 – 两者都

此外,您可以使用'B' 代替1'N' 代替2(以及'' 代替0)。结果将是'B',或'N',或'BN'。不过,不确定+ 是否可以用于连接。如果没有,请将CASEs 都放入CONCAT()

【讨论】:

  • 当我尝试执行此查询时,我出错:#1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 16 行的“DAYS AS Date UNION ALL SELECT CURDATE() + INTERVAL (2 - DAYOFWEEK) DAYS”附近使用正确的语法我真的不知道,出了什么问题在那里,因为我以前从未做过某种间隔,所以如果你能帮助我,我将不胜感激。谢谢。
  • @Robert: DAYOFWEEK 实际上应该是 DAYOFWEEK(CURDATE())。我的错,对不起。解决了这个问题。
  • 感谢您的努力,但我仍然收到相同的错误:#1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以了解在 'DAYS AS Date UNION ALL SELECT CURDATE() + INTERVAL (2 - DAYOFWEEK(CURDATE' at line 16) 附近使用的正确语法
  • @Robert:在区间表达式中将DAYS 更改为DAY。再次抱歉。
  • 嘿,再次感谢您的努力 :) 感谢上帝,第 16 行现在很清楚了。但是语法上还有一个错误。 #1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以了解在 'varchar(2)) + ' 附近使用的正确语法。 + CAST(DAY(week.Date) AS varchar(2)) IN ( CAST(MONTH' at line 24
【解决方案2】:

我不确定您的查询是否正确,但the MySQL docs 中提到了命令SYSDATE()。您可能想尝试以下方法:

... where date = SYSDATE() + 7

(检查语法,我来自Oracle;))

这将获得接下来 7 天的派对。

【讨论】:

  • 我认为,接下来的 7 天一点也不难,但本周呢?
  • 正确的链接是dev.mysql.com/doc/refman/5.0/en/…。由于相等运算符,这个查询(使用正确的函数)只会选择一个日期而不是一周。
  • 在函数中执行此操作,您可以查找一周中的实际日期,从那时起,您可以在变量中执行我上面使用的“+7”,该变量从“今天”获取值" 到 "下个星期日" 就像今天 = 星期一,星期天在 6 天(或 7 天,但你可以数它)所以变量是 +6 并且下周包括 +13 (6+7 = 13)
  • 如果您想要“本周”,您可以使用DAYOFWEEK 来获取当天的索引。然后,您可以在今天-星期几、今天+(星期几)之间进行 WHERE 生日,以获取“本周”的生日。但是你为什么要提醒用户过去的生日呢?除非他们的实际聚会迟到;)
猜你喜欢
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
  • 2012-12-09
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
相关资源
最近更新 更多