mysql使用date_sub按日期匹配

时间:2017-02-14 16:57:12

标签: mysql

我有这个mysql查询

SELECT *
FROM
  all_sent_Orders a
WHERE
  a.nachforschungCompletedOn IS NULL AND
  CASE WHEN a.lastMessageSent IS NOT NULL AND a.lastResponse IS NULL
    THEN
      date(date_sub(current_date, INTERVAL 7 DAY)) = date(a.lastMessageSent)
  ELSE
    (date(date_sub(current_date, INTERVAL 30 DAY)) = date(IFNULL(a.lastResponse, a.nachforschungSentOn))
     OR date(date_sub(current_date, INTERVAL 60 DAY)) = date(IFNULL(a.lastResponse, a.nachforschungSentOn))
     OR date(date_sub(current_date, INTERVAL 90 DAY)) = date(IFNULL(a.lastResponse, a.nachforschungSentOn))
     OR date(date_sub(current_date, INTERVAL 120 DAY)) = date(IFNULL(a.lastResponse, a.nachforschungSentOn)))
  END 

困扰我的是从ELSE开始的部分。我需要查找today - 30,60,90,120,150,... days的所有条目。有没有办法将多个OR重写为单个表达式,匹配相同的?

我在考虑一个循环,但这只会在一个过程中起作用。我想避免这种情况,但如果别无选择,那就可以了。

2 个答案:

答案 0 :(得分:1)

在您发表评论和更新后,我相信您需要的是HAVING而不是WHERE。 (*不正确,请参阅帖子的结尾,这两种情况都适用。)

因此,根据需要,应该是简化查询的内容:

考虑数据集:

INSERT INTO test2 (id, lastMessageSent, lastResponse, nachforschungSentOn)VALUES(1, date_sub(NOW(), INTERVAL 30 DAY), NULL, NULL);
INSERT INTO test2 (id, lastMessageSent, lastResponse, nachforschungSentOn)VALUES(2, date_sub(NOW(), INTERVAL 20 DAY), date_sub(NOW(), INTERVAL 60 DAY), NULL);
INSERT INTO test2 (id, lastMessageSent, lastResponse, nachforschungSentOn)VALUES(3, null, null, date_sub(NOW(), INTERVAL 90 DAY));

INSERT INTO test2 (id, lastMessageSent, lastResponse, nachforschungSentOn)VALUES(4, date_sub(NOW(), INTERVAL 29 DAY), NULL, NULL);
INSERT INTO test2 (id, lastMessageSent, lastResponse, nachforschungSentOn)VALUES(5, date_sub(NOW(), INTERVAL 20 DAY), date_sub(NOW(), INTERVAL 59 DAY), NULL);
INSERT INTO test2 (id, lastMessageSent, lastResponse, nachforschungSentOn)VALUES(6, null,null , date_sub(NOW(), INTERVAL 89 DAY));

哪会产生以下数据集:

enter image description here

并在2017-02-14上使用以下查询:

SELECT 
   a.* , 
   COALESCE( a.lastResponse, COALESCE( a.lastMessageSent, a.nachforschungSentOn ) ) AS relevantDate, 
   DATEDIFF( NOW( ) , COALESCE( a.lastResponse, COALESCE( a.lastMessageSent, a.nachforschungSentOn ) ) ) AS age
FROM 
  test2 a
HAVING 
  age
IN ( 30, 60, 90, 120, 150, 180 ) 

会产生以下结果,因为id 4,5,6在30天的倍数上不匹配(参见第二个没有子句的截图):

enter image description here

enter image description here

那是关于你的期望吗? (如果日期优先顺序不是"匹配",只需根据需要更改它们或添加min / max,如果null-thingy错误:))

编辑:

使用where它也应该有效,因为没有group by。 两者在性能上应该几乎相等,因为查询中没有join。 (如果存在联接,最好使用WHERE而不是HAVING(如果可能的话:where对聚合数据不起作用)因为它最小化了连接结果)

SELECT 
   a.* , 
   COALESCE( a.lastResponse, COALESCE( a.lastMessageSent, a.nachforschungSentOn ) ) AS relevantDate, 
   DATEDIFF( NOW( ) , COALESCE( a.lastResponse, COALESCE( a.lastMessageSent, a.nachforschungSentOn ) ) ) AS age
FROM 
  test2 a
WHERE
  DATEDIFF( NOW( ) , COALESCE( a.lastResponse, COALESCE( a.lastMessageSent, a.nachforschungSentOn ) ) )
IN ( 30, 60, 90, 120, 150, 180 ) 

pps。:正如您所看到的那样 - 解决方案中没有date_sub - 所以您的问题恰好是第一条评论中概述的XY问题 - 只是因为您认为{{1}可以解决这个问题。 :P

答案 1 :(得分:0)

这里可以使用Day()函数将今天的日期与提供的日期进行比较,我认为这样做符合您的要求:

SELECT *
FROM
  all_sent_Orders a
WHERE
  a.nachforschungCompletedOn IS NULL AND
  CASE WHEN a.lastMessageSent IS NOT NULL AND a.lastResponse IS NULL
    THEN
      date(date_sub(current_date, INTERVAL 1 WEEK)) = date(a.lastMessageSent)
  ELSE
    day(date(current_date)) = day(date(IFNULL(a.lastResponse, a.nachforschungSentOn)))
  END