MySQL Query用于计算2个月之间的天数

时间:2011-04-24 18:36:51

标签: mysql

我有2天像check_in(25/04/2011)和check_out(04/06/2011)。现在我需要计算月份日期之间的天数。

即。月 - 天,

April  -   5, 
May    -   31, 
June   -   4, 

请帮我构建mysql查询以获取上述结果。 提前谢谢。

4 个答案:

答案 0 :(得分:3)

如果您想在MySQL中严格完成,则需要创建一个存储过程来执行此操作。

根据存储过程这样的事情(范围不高于一年)。

DROP PROCEDURE IF EXISTS `getDateDiffBreakdown`;
CREATE PROCEDURE `getDateDiffBreakdown`(_DATE1 DATE,_DATE2 DATE)
BEGIN

IF (MONTH(_DATE1)<>MONTH(_DATE2)) THEN
-- we detected a month change
-- compute the selection based on current date and last day of month
SELECT CONCAT(DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(LAST_DAY(_DATE1))-TO_DAYS(_DATE1)+1);
-- step into next month and re-run the calc
call getDateDiffBreakdown(DATE_ADD(LAST_DAY(_DATE1),INTERVAL 1 DAY),_DATE2);

ELSE
-- same month, do the calculation
SELECT CONCAT(DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(_DATE2)-TO_DAYS(_DATE1)+1);
END IF;

END;

这样打电话:

set max_sp_recursion_depth = 11;
call getDateDiffBreakdown('2011-12-11','2012-06-03');

<强>更新

另一种获得1行的方法是:

DROP PROCEDURE IF EXISTS `getDateDiffBreakdown2`;
CREATE PROCEDURE `getDateDiffBreakdown2`(IN _DATE1 DATE,IN _DATE2 DATE, INOUT _RETURN VARCHAR(1000))
BEGIN

IF (MONTH(_DATE1)<>MONTH(_DATE2)) THEN
-- we detected a month change
-- compute the selection based on current date and last day of month
SET _RETURN=CONCAT(_RETURN,DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(LAST_DAY(_DATE1))-TO_DAYS(_DATE1)+1);
SET _RETURN = CONCAT(_RETURN,",");
-- step into next month and re-run the calc
call getDateDiffBreakdown2(DATE_ADD(LAST_DAY(_DATE1),INTERVAL 1 DAY),_DATE2,_RETURN);

ELSE
-- same month, do the calculation
SET _RETURN=CONCAT(_RETURN,DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(_DATE2)-TO_DAYS(_DATE1)+1);
END IF;

END;

这样打电话:

set max_sp_recursion_depth = 255;
set @TEMP = '';
call getDateDiffBreakdown2('2011-12-11','2012-06-03',@TEMP);
SELECT @TEMP;

答案 1 :(得分:1)

我也试图解决这个问题。 Pentium10太强了,现在我会尝试他的解决方案。 :) 顺便说一下,这是我的。

delimiter //
drop procedure if exists groupDaysByMonth//
create procedure groupDaysByMonth(in dStart date,in dEnd date)
begin
declare i int default 0;
declare months,days int;
drop table if exists t;
create temporary table t (
month_year varchar(50),
daysNum int
);
set months = (select period_diff(date_format(dEnd,'%Y%m'),date_format(dStart,'%Y%m')));
while i<=months do
if months = 0 then
set days = (select datediff(dEnd,dStart));
elseif i = 0 then
set days = ( select datediff(concat(date_format(dStart,'%Y-%m-'),day(last_day(dStart))),dStart));
elseif months = i then
set days = (select datediff(dEnd,date_format(dEnd,'%Y-%m-01'))+1);
else
set days = ( select day(last_day(dStart + interval i month)));
end if;
insert into t (month_year,daysNum) values(date_format(dStart + interval i month,'%M %Y'),days);
set i = i + 1;
end while;
select * from t;
end //
delimiter ;


mysql> call groupDaysByMonth('2011-04-25','2011-04-30');
+------------+---------+
| month_year | daysNum |
+------------+---------+
| April 2011 |       5 |
+------------+---------+
1 row in set (0.01 sec)

mysql> call groupDaysByMonth('2011-04-25','2011-06-04');
+------------+---------+
| month_year | daysNum |
+------------+---------+
| April 2011 |       5 |
| May 2011   |      31 |
| June 2011  |       4 |
+------------+---------+
3 rows in set (0.01 sec)

Query OK, 0 rows affected (0.01 sec)


mysql> call groupDaysByMonth('2011-09-25','2012-05-02');
+----------------+---------+
| month_year     | daysNum |
+----------------+---------+
| September 2011 |       5 |
| October 2011   |      31 |
| November 2011  |      30 |
| December 2011  |      31 |
| January 2012   |      31 |
| February 2012  |      29 |
| March 2012     |      31 |
| April 2012     |      30 |
| May 2012       |       2 |
+----------------+---------+
9 rows in set (0.01 sec)

Query OK, 0 rows affected (0.03 sec)

希望它有所帮助。

答案 2 :(得分:1)

    Follow Answer 1 -- i am using it for multi year n the result set is month number with year and then the days of month   format is "month number - last two digit of year - total days in month."

you can change the format of display according your need


**UPDATE**

In another approach to get in 1 line, it would be:

    DROP PROCEDURE IF EXISTS `getDateDiffBreakdown2`;
    CREATE PROCEDURE `getDateDiffBreakdown2`(IN _DATE1 DATE,IN _DATE2 DATE, INOUT _RETURN VARCHAR(1000))
    BEGIN

    IF (MONTH(_DATE1)<>MONTH(_DATE2)) THEN
    -- we detected a month change
    -- compute the selection based on current date and last day of month
    SET _RETURN=CONCAT(_RETURN,DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(LAST_DAY(_DATE1))-TO_DAYS(_DATE1)+1);
    SET _RETURN = CONCAT(_RETURN,",");
    -- step into next month and re-run the calc
    call getDateDiffBreakdown2(DATE_ADD(LAST_DAY(_DATE1),INTERVAL 1 DAY),_DATE2,_RETURN);

    ELSE
    -- same month, do the calculation
    SET _RETURN=CONCAT(_RETURN,DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(_DATE2)-TO_DAYS(_DATE1)+1);
    END IF;

    END;

call like this:

    set max_sp_recursion_depth = 255;
    set @TEMP = '';
    call getDateDiffBreakdown2('2011-12-11','2012-06-03',@TEMP);
    SELECT @TEMP;









I have applied this post in one of my requirement but i found it buggy. i can be wrong if any one prove it and provide a better solution.

look how i am calling it and what i am getting :

   set max_sp_recursion_depth = 255;
    set @TEMP = '';
    call getDateDiffBreakdown2('2010-12-10' , '2011-12-10',@TEMP);
    SELECT @TEMP;


in result i get :  '12 - 10 - 366'

year is changed but month is same.

i have tweaked the function as following: kindly let me know if some thing is strange. thanks




 DROP PROCEDURE IF EXISTS `getDateDiffBreakdown2`;
    CREATE PROCEDURE `getDateDiffBreakdown2`(IN _DATE1 DATE,IN _DATE2 DATE, INOUT _RETURN VARCHAR(1000))
    BEGIN

    IF(YEAR(_DATE1)<>YEAR(_DATE2)) THEN

SET _RETURN=CONCAT(_RETURN,DATE_FORMAT(_DATE1,'%b - %y'),' - ',TO_DAYS(LAST_DAY(_DATE1))-TO_DAYS(_DATE1)+1);
SET _RETURN = CONCAT(_RETURN,",");
-- step into next month and re-run the calc
call getDateDiffBreakdown2(DATE_ADD(LAST_DAY(_DATE1),INTERVAL 1 DAY),_DATE2,_RETURN);

ELSEIF (MONTH(_DATE1)<>MONTH(_DATE2)) THEN
    -- we detected a month change
    -- compute the selection based on current date and last day of month
    SET _RETURN=CONCAT(_RETURN,DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(LAST_DAY(_DATE1))-TO_DAYS(_DATE1)+1);
    SET _RETURN = CONCAT(_RETURN,",");
    -- step into next month and re-run the calc
    call getDateDiffBreakdown2(DATE_ADD(LAST_DAY(_DATE1),INTERVAL 1 DAY),_DATE2,_RETURN);

    ELSE
    -- same month, do the calculation
    SET _RETURN=CONCAT(_RETURN,DATE_FORMAT(_DATE1,'%M'),' - ',TO_DAYS(_DATE2)-TO_DAYS(_DATE1)+1);
    END IF;

    END;

答案 3 :(得分:0)

使用TO_DAYS(日期)功能。