我有2天check_in(25/04/2011)和check_out(04/06/2011)。现在我需要计算月份之间日期之间的日期。用于计算2dates组之间的天数的MySQL查询
即。月 - 天,
April - 5,
May - 31,
June - 4,
请帮我建立mysql查询以获得上述结果。 在此先感谢。
我有2天check_in(25/04/2011)和check_out(04/06/2011)。现在我需要计算月份之间日期之间的日期。用于计算2dates组之间的天数的MySQL查询
即。月 - 天,
April - 5,
May - 31,
June - 4,
请帮我建立mysql查询以获得上述结果。 在此先感谢。
使用TO_DAYS(日期)函数。
事情是我需要计算check_in(25/04/2011)和check_out(04/06/2011)之间的差异。使用datediff()我得到的答案为40天。但我希望具体如上所述。即4月5日, 5月31日, 6月4日, – Surya 2011-04-24 18:51:42
如果你想严格在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');
UPDATE
在另一种方法在1号线搞定,那就是:
调用是这样的:
set max_sp_recursion_depth = 255;
set @TEMP = '';
call getDateDiffBreakdown2('2011-12-11','2012-06-03',@TEMP);
SELECT @TEMP;
+1现在就测试您的解决方案。你总是很酷。 :) – 2011-04-24 21:42:52
谢谢,我会让OP或其他人调整代码以适应从不同年份的多个月的范围工作。 – Pentium10 2011-04-24 21:44:36
我也试图解决这个问题。 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)
希望它有帮助。
谢谢,这是我想要的。让我试试这个。 – Surya 2011-04-25 06:03:48
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;
你会更好的计算这个客户端。 MySQL有很棒的日期函数,但是你会使查询不必要地复杂 – 2011-04-24 19:04:12
问题是我需要查询来生成报告。否则,我可能不得不编写程序逻辑。 – Surya 2011-04-24 20:15:02
你会如何使用输出?这些行是新的选择,还是应该放在1列中? – Pentium10 2011-04-24 20:20:03