MySQL 日期时间与前一行的比较

Posted

技术标签:

【中文标题】MySQL 日期时间与前一行的比较【英文标题】:MySQL datetime comparison with previous row 【发布时间】:2012-04-09 20:13:19 【问题描述】:

我有一个包含两个日期列的表。 DATE1 有时为 NULL,有时包含重复值。 DATE2 始终填充且唯一。我的表格按最新的 DATE2 日期排序。

我想创建一个新的日期列,其中 DATE1 将被选中,除非它的值与下一行重复或者它为 NULL。在这种情况下,我想取 DATE2 的值。我还需要两个布尔列来告诉我什么时候满足这些条件。让我用一个例子来演示一下,这样更清楚。

在下表中,第 5 行和第 6 行的值为 2011 年 7 月 27 日,所以我想将第 5 行的新日期列设置为 2011 年 8 月 4 日(即 DATE2)。在第 3 行,DATE1 的值为 NULL,所以我想取 DATE2 的值。

我尝试了一些内部选择语句,但无法使其正常工作。有什么想法吗?

我的表目前在数据库中:

    Row     DATE1           DATE2
    --------------------------------------
    1       Oct 10, 2011    Nov 13, 2011    
    2       Oct 10, 2011    Oct 10, 2011    
    3       NULL            Oct 8, 2011     
    4       Aug 12, 2011    Aug 12, 2011    
    5       Jul 27, 2011    Aug 4, 2011     
    6       Jul 27, 2011    Jul 28, 2011    
    7       Jul 1, 2011     Jul 26, 2011    
    8       May 24, 2011    Jun 13, 2011

我期望的最终结果如下:

    Row     FINAL_DATE      DATE1_DUPLICATE   DATE1_WAS_NULL
    ----------------------------------------------------------
    1       Nov 13, 2011    TRUE              FALSE   
    2       Oct 10, 2011    FALSE             FALSE
    3       Oct 8, 2011     FALSE             TRUE
    4       Aug 12, 2011    FALSE             FALSE
    5       Aug 4, 2011     TRUE              FALSE 
    6       Jul 27, 2011    FALSE             FALSE
    7       Jul 1, 2011     FALSE             FALSE
    8       May 24, 2011    FALSE             FALSE

非常感谢!

【问题讨论】:

@MattFenwick 我在查询多行的意义上使用标签,而不是特定于任何类型的 SQL。如果您认为它具有误导性,您能推荐一个更好的标签吗? @MattFenwick 好电话,你读懂了我的想法。 【参考方案1】:

这可以通过顺序扫描表和使用 mysql 变量来处理。您可以在 (updated) SQL-fiddle:

进行测试
SELECT date2
     , dd 
     , DATE_FORMAT(dd, '%b %e, %Y') AS final_date
     , date1_duplicate
     , date1_was_null
FROM
( SELECT date2
       , COALESCE( (date1 = @d OR date1 = @prev), FALSE)
           AS date1_duplicate
       , (date1 IS NULL)               AS date1_was_null
       , @d := CASE WHEN (date1 = @d OR date1 = @prev) 
                 THEN date2 
                 ELSE COALESCE(date1, date2) 
               END AS dd
       , @prev := date1 AS pre
  FROM tableX AS t
    CROSS JOIN
      ( SELECT @d := DATE('1000-01-01')
             , @prev := @d 
      ) AS dummy
  ORDER BY date2 ASC 
) AS tmp
ORDER BY date2 DESC
;

【讨论】:

非常接近。唯一的问题是它在检查是否使用 date2 列时不采用新计算的日期。这是一个示例:sqlfiddle.com/#!2/5063c/3 第 4 行应该是 11 月 19 日,而不是 10 月 10 日,因为按 date2 排序的下一行包含重复项...... 我的意思是说“唯一的问题是它在检查时不会采用旧日期......”。我希望你明白我的意思。 @http203:更新了查询。再次测试。 太好了,谢谢。我在这里有类似的东西:sqlfiddle.com/#!2/5063c/10 不过有一个问题:你为什么不在第一次选择中检查 date1 IS NOT NULL ?这是不必要的吗? 是的,那张支票(或类似的东西)也应该在那里。您现在可能在该列中除了 True 和 False 之外还有 Null。

以上是关于MySQL 日期时间与前一行的比较的主要内容,如果未能解决你的问题,请参考以下文章

如何仅选择至少一个值与前一行发生更改的行

MySQL为每一行自动存储日期时间

带有 UNIX 时间戳的 MySQL 表 - 按时间戳排序并计算一行与前一行之间的差异

比较两个日期分区上的同一行

hql日期和字符串的比较

将日期和时间与 MySQL 中的当前时间进行比较