mysql - 如何在MySQL中以年、月、日为单位求和持续时间?

标签 mysql datetime

我有一个表持续时间:

-------------------------------
| id |    from    |     to    |
|----|------------|-----------|
|  1 | 2011-02-22 |    NULL   |
|  2 | 1999-08-03 |2005-03-30 |
|  3 | 1982-09-03 |1988-01-30 |
|  4 | 1965-12-01 |1980-05-02 |
-------------------------------

我想计算连续的时间差(往返)并将它们相加。我的查询是:

SELECT CONCAT(SUM(TIMESTAMPDIFF( YEAR, from, IF(to IS NULL,'2017-10-
18', to))),' Years ',
SUM(TIMESTAMPDIFF( MONTH, from, IF(to IS NULL,'2017-10-18', to)) 
% 12),' Months ',
SUM(FLOOR( TIMESTAMPDIFF( DAY, from, IF(to IS NULL,'2017-10-18', 
to)) % 30.4375 )),' Days ') AS Duration
FROM duration;

我得到:

------------------------------
|         Duration           |
|----------------------------|
| 30 Years 23 Months 78 Days |
------------------------------

但我想得到:

-----------------------------
|         Duration          |
|---------------------------|
| 32 Years 1 Months 18 Days |
-----------------------------

请帮忙!

最佳答案

我尝试在下面提出一系列查询,以显示确定以年/月/日为单位的持续时间的准确方法(尽管这些计算结果为32 年 1 个月 22 天(可能是由于“现在”的变化),并且我没有添加最终的连接,这并不难实现。所使用的方法每行都是准确的,但确实依赖于每月天数的近似值(30.4375 *) 用于最终计算月份和日期。

  1. TIMESTAMPDIFF(YEAR , from_dt, to_dt ) 给出每行的年数
  2. TIMESTAMPDIFF(MONTH, from_dt + INTERVAL TIMESTAMPDIFF(YEAR , from_dt, to_dt) YEAR , to_dt ) 将年数添加到开始日期,然后获取该日期与结束日期的差值几个月内
  3. TIMESTAMPDIFF(DAY , from_dt + INTERVAL TIMESTAMPDIFF(MONTH, from_dt, to_dt) MONTH , to_dt ) 现在将总月数添加到开始日期,然后计算到达结束日期的剩余时间日期
  4. 请注意,如果给定开始日期 + 年 + 月 + 天,则可以准确地重新计算结束日期(请参阅查询 4)

注意:我在下面的查询中使用了多个“层”,使它们更易于阅读(我希望)。

SQL Fiddle

MySQL 5.6 架构设置:

CREATE TABLE duration
  ( 
     from_dt DATE,  to_dt DATE 
  ); 

INSERT INTO duration 
VALUES  ('2011-02-22', NULL )
      , ('1999-08-03', '2005-03-30' )
      , ('1982-09-03', '1988-01-30' )
      , ('1965-12-01', '1980-05-02' )
; 

查询 1:

## adjusted sums( method using timestampdiff ) 
SELECT
      CASE WHEN SUM(d.months) > 12 THEN SUM(d.years) + FLOOR(SUM(d.years/12)) ELSE SUM(d.years) END
      as years
    , CASE WHEN SUM(d.days) > 30 THEN FLOOR(((SUM(d.months) + FLOOR(SUM(d.days/30.4375)))/12)) ELSE SUM(d.months) END
      as months
    , CASE WHEN SUM(d.days) > 30 THEN FLOOR(MOD(SUM(d.days), 30)) ELSE SUM(d.months) END
      as days
    , current_date
FROM (
      SELECT
              TIMESTAMPDIFF(YEAR , from_dt, to_dt )
              as years
            , TIMESTAMPDIFF(MONTH, from_dt + INTERVAL TIMESTAMPDIFF(YEAR , from_dt, to_dt) YEAR  , to_dt )
              as months
            , TIMESTAMPDIFF(DAY  , from_dt + INTERVAL TIMESTAMPDIFF(MONTH, from_dt, to_dt) MONTH , to_dt )
              as days
      FROM (
            SELECT
                 from_dt
                , COALESCE(to_dt,CURRENT_DATE) to_dt
            FROM duration
          ) d2
    ) d

<强> Results :

| years | months | days | current_date |
|-------|--------|------|--------------|
|    32 |      2 |   22 |   2017-10-19 |

查询 2:

## simple sums( method using timestampdiff )
SELECT
        sum(TIMESTAMPDIFF(YEAR , from_dt, to_dt ))
        years
      , sum(TIMESTAMPDIFF(MONTH, from_dt + INTERVAL TIMESTAMPDIFF(YEAR , from_dt, to_dt) YEAR  , to_dt ))
        months
      , sum(TIMESTAMPDIFF(DAY  , from_dt + INTERVAL TIMESTAMPDIFF(MONTH, from_dt, to_dt) MONTH , to_dt ))
        days
      , current_date
FROM (
      SELECT
           from_dt
          , COALESCE(to_dt,CURRENT_DATE) to_dt
      FROM duration
    ) d

<强> Results :

| years | months | days | current_date |
|-------|--------|------|--------------|
|    30 |     23 |   82 |   2017-10-19 |

查询 3:

## method using timestampdiff
SELECT
        d.*
      , TIMESTAMPDIFF(YEAR , from_dt, to_dt )                                                        AS diff_yr
      , TIMESTAMPDIFF(MONTH, from_dt + INTERVAL TIMESTAMPDIFF(YEAR , from_dt, to_dt) YEAR  , to_dt ) AS diff_mn
      , TIMESTAMPDIFF(DAY  , from_dt + INTERVAL TIMESTAMPDIFF(MONTH, from_dt, to_dt) MONTH , to_dt ) AS diff_dy
FROM (
      SELECT
           from_dt
          , COALESCE(to_dt,CURRENT_DATE) to_dt
          , current_date
      FROM duration
    ) d

<强> Results :

|    from_dt |      to_dt | current_date | diff_yr | diff_mn | diff_dy |
|------------|------------|--------------|---------|---------|---------|
| 2011-02-22 | 2017-10-19 |   2017-10-19 |       6 |       7 |      27 |
| 1999-08-03 | 2005-03-30 |   2017-10-19 |       5 |       7 |      27 |
| 1982-09-03 | 1988-01-30 |   2017-10-19 |       5 |       4 |      27 |
| 1965-12-01 | 1980-05-02 |   2017-10-19 |      14 |       5 |       1 |

查询 4:

## testing (method using timestampdiff)
## is able to reproduce to_dt ?
select
      from_dt
    , to_dt
    , from_dt + INTERVAL diff_yr YEAR
              + INTERVAL diff_mn MONTH
              + INTERVAL diff_dy DAY
      recalculated_to_dt
    , current_date
FROM (
      SELECT
              d.*
            , TIMESTAMPDIFF(YEAR , from_dt, to_dt )                                                                    AS diff_yr
            , TIMESTAMPDIFF(MONTH, from_dt + INTERVAL TIMESTAMPDIFF(YEAR , from_dt, to_dt) YEAR  , to_dt ) AS diff_mn
            , TIMESTAMPDIFF(DAY  , from_dt + INTERVAL TIMESTAMPDIFF(MONTH, from_dt, to_dt) MONTH , to_dt ) AS diff_dy
      FROM (
            SELECT
                 from_dt
                , COALESCE(to_dt,CURRENT_DATE) to_dt
            FROM duration
          ) d
    ) d2

<强> Results :

|    from_dt |      to_dt | recalculated_to_dt | current_date |
|------------|------------|--------------------|--------------|
| 2011-02-22 | 2017-10-19 |         2017-10-19 |   2017-10-19 |
| 1999-08-03 | 2005-03-30 |         2005-03-30 |   2017-10-19 |
| 1982-09-03 | 1988-01-30 |         1988-01-30 |   2017-10-19 |
| 1965-12-01 | 1980-05-02 |         1980-05-02 |   2017-10-19 |
  • 30.4375我相信是〜(一个世纪的天数)/120

关于mysql - 如何在MySQL中以年、月、日为单位求和持续时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46816341/

相关文章:

PHP 根据 <selection> 中的选定选项检索 mysql 存储的字符数据返回错误的字符

php - 一种将存储在 mysql 中的数据从一个人发送给另一个人的安全方法

php - 从 Laravel 5 中的一种形式插入不同的表

r - 如何在R中仅创建时间

Ruby 确定季节(秋季、冬季、 Spring 或夏季)

python - MySQLdb 注册程序?

java - 使用java将大量数据存储到mysql的最佳方法

sql - 显示外出状态的最新日期

python - 在 Python 中使用 Pandas 重复年度循环

python - 在 pandas/numpy 中将 float 转换为小时和分钟