嵌套的MySQL案例包括日期函数

时间:2013-09-09 07:58:48

标签: mysql date case

我有一个具有以下结构的MySQL表:

    id |    date    |  type   |     description
    ---------------------------------------------------
     0 | 1979-09-20 | 'bday'  | 'Birthday Employee1 '
     1 | 1984-05-04 | 'bday'  | 'Birthday Employee2 '
     2 | 1989-01-04 | 'bday'  | 'Birthday Employee3 '
     3 | 2013-10-10 | 'visit' | 'Visit of Visitor1  '

此表应处理员工门户中所有即将发生和过去的事件。 有两种不同类型的事件;生日和访问。这些在列类型中声明为字符串。 生日只应输入一次,而不是每年输入,因此需要一个复杂的查询来处理这种情况:

   SELECT * ,
   CASE type
   WHEN 'bday'
   THEN
     (CASE 
      WHEN ADDDATE( date, INTERVAL YEAR( NOW( ) ) - YEAR( date ) YEAR )< NOW()
       THEN ADDDATE(ADDDATE(datum,INTERVAL YEAR(NOW())- YEAR(date) YEAR),
       INTERVAL 1 YEAR)
       ELSE ADDDATE( date, INTERVAL YEAR( NOW( ) ) - YEAR( date ) YEAR )
     END)
   ELSE date
   END 
   AS dates
   FROM events
   WHERE date > NOW() AND type='visit' OR ADDDATE(date, INTERVAL 
   YEAR NOW())-YEAR( date ) YEAR) > NOW() AND type='bday'
   ORDER BY dates ASC
   LIMIT 0 ,10

这个查询对我来说不起作用,因为我在括号中添加了嵌套的case子句。我将其替换为以下行

   ADDDATE( date, INTERVAL YEAR( NOW( ) ) - YEAR( date ) YEAR )

这有效但问题是 - 正如您在嵌套的CASE条款中所看到的那样 - 最近一年已经发生的生日不会被选中。因此,额外CASE的目的是确定年份应该是2013年还是2014年(如果它已经在2013年发生)。

这对于今年头两个星期的生日非常重要。提醒通知必须在前一年看到,否则它不会有那么大意义。

所以实际上我只需要弄清楚为什么嵌套的CASE子句不起作用。也有可能有更明智的方法来解决这个问题,但现在我无法看到它们。

2 个答案:

答案 0 :(得分:1)

我想你想展示“近”未来的事件和生日。一种方法是将逻辑分成3部分并UNION。这三部分将是:

  • 访问
  • 今年的生日
  • 明年的生日

    ( SELECT id, date, type, description, 
             date AS dates
      FROM events
      WHERE type='visit' 
        AND date > NOW() 
    )
    UNION ALL
    ( SELECT id, date, type, description,
             ADDDATE(date, INTERVAL (YEAR(NOW())-YEAR(date)) YEAR)
      FROM events
      WHERE type='bday'
        AND ADDDATE(date, INTERVAL (YEAR(NOW())-YEAR(date)) YEAR) > NOW()
    )
    UNION ALL
    ( SELECT id, date, type, description,
             ADDDATE(date, INTERVAL (1+YEAR(NOW())-YEAR(date)) YEAR)
      FROM events
      WHERE type='bday'
    )
    ORDER BY dates ASC
    LIMIT 0, 10 ;
    

您的CASE似乎也是正确的。但是,如果您想要考虑所有生日,则应将OR ADDDATE(date, INTERVAL YEAR NOW())-YEAR( date ) YEAR) > NOW() AND type='bday'条件替换为简单OR type='bday'

答案 1 :(得分:0)

您必须更改YEAR DIFF部分:

SELECT ADDDATE(date, INTERVAL (FLOOR(DATEDIFF(CURDATE(),date)/365)) YEAR )<NOW()

id = 0

的示例
SELECT ADDDATE('1979-09-20', 
INTERVAL (FLOOR(DATEDIFF(CURDATE(),'1979-09-20')/365)) YEAR )< NOW();