Related
I have a query :
insert into fookoo_business
select stat_date, sum(spend), sum(revenue)
from hooloo_business;
that i want to run for each date from '2017-01-20' until yesterday (it means the query will run 434 times if we're at 01/04/2018), for each date separately
(in a loop).
how can i create a loop in Mysql to do it for me?
I have tried:
creating procedure for the query select #stat_date, sum(spend), sum(revenue)
I called 'query'
then :
CREATE PROCEDURE loop_procedure()
BEGIN
SET #stat_date='2018-03-20';
CALL 'query';
REPEAT
SET #stat_date = #stat_date + INTERVAL 1 DAY;
UNTIL #stat_date = CURDATE() END REPEAT;
END
eventually i've used the following logic within a stored procedure to fetch the data:
PROCEDURE `x_monitoring_loop`()
BEGIN
DECLARE i INT;
DECLARE len INT;
SET len = 434;
SET i = 0;
WHILE (i < len) DO
SET #stat_date= CURDATE()-INTERVAL 1 DAY;
SET #stat_date= #stat_date- INTERVAL i DAY;
Insert query;
SET i = i +1;
END WHILE;
This way the query ran 434 times for each day, beginning at current date - 1 day.
I do not know why you want to use a procedure,I think we can just use a query sql to do it:
INSERT INTO fookoo_business
SELECT stat_date, SUM(spend), SUM(revenue)
FROM hooloo_business
WHERE stat_date BETWEEN STR_TO_DATE('2017-01-02', '%Y-%m-%d') -- start date
AND DATE_SUB(NOW(), INTERVAL 1 DAY) -- end date
GROUP BY stat_date;
Id | starttime | endtime |
1 | 1999-05-07 15:00 | 1999-05-07 16:45 |
How do I get it interval of 1 minute from the start time to the end time.
So I want something like this 15:01, 15:02.
Please any help will be appreciated new to sql and trying to learn it as best I can. Thanks
NOTE :
I don't want the whole minute. I want to get every minute from start to end I need it to count the users that logged in every minute of the game if that makes any sense
SELECT *,TIMESTAMPDIFF(MINUTE,starttime,endtime) FROM Table1
Create this function
CREATE function getTimeAll(id1 int)
RETURNS VARCHAR(65535) DETERMINISTIC
BEGIN
DECLARE time1 varchar(65535);
DECLARE intrvlMin int;
DECLARE c int;
SET intrvlMin=(SELECT TIMESTAMPDIFF(MINUTE,starttime,endtime) FROM Table1 WHERE id = id1);
SET c=1;
SET time1 = '';
While c < intrvlMin
do
SET time1=CONCAT(time1,(SELECT date_format(date_add(starttime,interval c minute),'%H:%i') FROM Table1 WHERE id = id1),',');
SET c = c + 1;
end WHILE;
SET time1=CONCAT(time1,(SELECT date_format(date_add(starttime,interval c minute),'%H:%i') FROM Table1 WHERE id = id1));
RETURN time1;
END ;
Then Run
SELECT `Id`, `starttime`, `endtime`,getTimeAll(`Id`) AS Times FROM Table1;
output
Id starttime endtime Times
1 1999-05-07 15:00:00 1999-05-07 16:45:00 15:01,15:02,15:03,15:04,15:05,15:06,15:07,15:08,15:09,15:10,15:11,15:12,15:13,15:14,15:15,15:16,15:17,15:18,15:19,15:20,15:21,15:22,15:23,15:24,15:25,15:26,15:27,15:28,15:29,15:30,15:31,15:32,15:33,15:34,15:35,15:36,15:37,15:38,15:39,15:40,15:41,15:42,15:43,15:44,15:45,15:46,15:47,15:48,15:49,15:50,15:51,15:52,15:53,15:54,15:55,15:56,15:57,15:58,15:59,16:00,16:01,16:02,16:03,16:04,16:05,16:06,16:07,16:08,16:09,16:10,16:11,16:12,16:13,16:14,16:15,16:16,16:17,16:18,16:19,16:20,16:21,16:22,16:23,16:24,16:25,16:26,16:27,16:28,16:29,16:30,16:31,16:32,16:33,16:34,16:35,16:36,16:37,16:38,16:39,16:40,16:41,16:42,16:43,16:44,16:45
DEMO
https://www.db-fiddle.com/f/nge35TSTWyd3pLSw6X1TE4/2
You might need to use loop ,
Firstly
select TIMESTAMPDIFF(minute,starttime,endtime) from table1
Here you will get 105
This calculates number of minutes between 2 times
SELECT date_format(date_add(starttime,interval 1 minute),'%H:%i') from table1
SELECT date_format(date_add(starttime,interval 2 minute),'%H:%i') from table1
SELECT date_format(date_add(starttime,interval 3 minute),'%H:%i') from table1
loop this till 105 times with increment interval time
I am developing a Java application using MySQL. I need to know which is the week of each month, of the stored dates. Is there any MySQL function for that ? Basically , if i was to use this for the current date (13.09) it would show me its in week number 2 and tomorrow it will be week number 3.
You can play with the WEEK() function, and see if it suits your needs. Here I'm using WEEK(date, 3) that will return the week of the year from 1 to 53, starting from Mondays:
set #my_date = '2015-09-13';
SELECT
WEEK(#my_date, 3) -
WEEK(#my_date - INTERVAL DAY(#my_date)-1 DAY, 3) + 1
AS week_number;
WEEK(date, 3) will return the week of the year of the selected date
WEEK(date - INTERVAL DAY(#my_date)-1 DAY, 3) will return the week of the year of the first day of the month of the selected date
It will return 1 for 01-March-2015 (because it's the first day of the month so it's week 1) and 2 for 02-March-2015 (because weeks starts from Mondays, so it's a new week). If this is not the desidered behaviour you should specify your requirements more precisely.
Please see a fiddle here.
Unfortunately, there isn't a "weekofmonth" function, but you could use dayofmonth, and manipulate the result a bit:
SELECT CURRENT_DATE(),
FLOOR((DAYOFMONTH(CURRENT_DATE()) - 1) / 7) + 1 AS week_of_month
Create a mysql function.
CREATE FUNCTION `WEEK_OF_MONTH`(
datee DATE
) RETURNS INT(11)
BEGIN
DECLARE DayNamee VARCHAR(20);
DECLARE StartDatee DATE;
DECLARE DayNumber INT DEFAULT 0;
SET DayNamee = (SELECT DAYNAME(datee));
SET StartDatee = (SELECT FIRST_DAY(datee));
WHILE StartDatee <= datee DO
IF DayNamee = DAYNAME(StartDatee) THEN
SET DayNumber = DayNumber + 1;
END IF;
SET StartDatee = DATE_ADD( StartDatee, INTERVAL 1 DAY);
END WHILE;
RETURN DayNumber;
END$$
DELIMITER ;
Call as --
SELECT `WEEK_OF_MONTH`('2018-12-31');
Result : 5
How would I put together a query to display all of the hours in the next week as I want to compare a timetable against this for appointment purposes.
Thanks for any help!
edit--
the expected result would be great as between 9 to 5
| client_date | client_time |
10/01/2010 09:00:00
10/01/2010 10:00:00
10/01/2010 11:00:00
10/01/2010 12:00:00
10/01/2010 13:00:00
10/01/2010 14:00:00
10/01/2010 15:00:00
10/01/2010 16:00:00
10/01/2010 17:00:00
You will need to create a table to store the date and time values.
CREATE TABLE calendarhours (caldaytime DATETIME);
You will then need to create a stored procedure to loop through the two dates and insert the date time values for the time sheet times into the table.
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `timesheetdays`(startdate DATETIME, enddate DATETIME)
BEGIN
DECLARE tempdate DATETIME;
DELETE FROM `calendarhours`;
-- set the temp date to 9am of the start date
SET tempdate = DATE_ADD(DATE(startdate), INTERVAL '0 9' DAY_HOUR);
-- while the temp date is less than or equal to the end date, insert the date
-- into the temp table
WHILE ( tempdate <= enddate ) DO
BEGIN
-- insert temp date into temp table
INSERT INTO `calendarhours` (caldaytime) VALUES (tempdate);
-- increment temp date by an hour
SET tempdate = DATE_ADD(tempdate, INTERVAL '0 1' DAY_HOUR);
-- if the temp date is greater than 5 PM (17:00) then increment to the next day
IF TIMEDIFF(tempdate, DATE_ADD(DATE(tempdate), INTERVAL '0 17' DAY_HOUR)) > 0 THEN
BEGIN
-- increment to the next day
SET tempdate = DATE_ADD(DATE(tempdate), INTERVAL '1 9' DAY_HOUR);
-- for business purposes, if the day is a Saturday or a Sunday increment
-- until we reach Monday
WHILE ( DAYNAME(tempdate) = 'Saturday' OR DAYNAME(tempdate) = 'Sunday' ) DO
BEGIN
SET tempdate = DATE_ADD(DATE(tempdate), INTERVAL '1 9' DAY_HOUR);
END;
END WHILE;
END;
END IF;
END;
END WHILE;
-- return all the inserted date and times
SELECT * FROM calendarhours ORDER BY caldaytime;
END
This procedure will then loop through the two dates, starting from 9 am each day and finishing at 5pm each day (17:00). When the time reaches 18:00, the procedure increments to the next day and starts again at 9 am.
If you are doing a standard business week timesheet, then if the day is equal to Saturday or Sunday, it will increment until it reaches Monday.
To test this I used the following statements:
CALL `timesheetdays`(NOW(), DATE_ADD(DATE(NOW()), INTERVAL '5 0' DAY_HOUR));
SELECT * FROM `calendarhours`;
This tests the procedure from today to 5 days from today and shows the hours as required. The first statement adds the records to the table and then returns the records, the second statement returns the records from the table.
you can use a temporary table in a stored procedure.
DELIMITER ;;
DROP PROCEDURE IF EXISTS ListHours ;;
CREATE PROCEDURE ListHours()
BEGIN
DECLARE curDT DATETIME;
DECLARE today DATETIME ;
DECLARE nextSaturday DATETIME;
DECLARE nextSunday DATETIME;
DECLARE iterDate DATETIME;
DECLARE iterDateTime DATETIME;
DECLARE iterBound DATETIME;
DECLARE resDate DATETIME;
DECLARE resTime DATETIME;
DECLARE delta INT;
DROP TABLE IF EXISTS tempNextWeek;
CREATE TEMPORARY TABLE IF NOT EXISTS tempNextWeek
(
client_date VARCHAR(20),
client_time VARCHAR(20)
);
DELETE FROM tempNextWeek;
SET curDT = NOW();
SET today = ADDTIME(SUBTIME(curDT , TIME(curDT)) , '9:0:0');
SET delta = 8 - DAYOFWEEK(today);
SET nextSunday = ADDDATE(today , INTERVAL delta DAY);
SET nextSaturday = ADDTIME(nextSunday , '6 0:0:0');
-- select today , delta , nextSaturday , nextSunday ;
SET iterDate = nextSunday;
WHILE iterDate <= nextSaturday DO
SET iterDateTime = iterDate;
SET iterBound = ADDTIME(iterDateTime, '8:0:0');
WHILE iterDateTIme <= iterBound DO
INSERT tempNextWeek (client_date, client_time) VALUE ( DATE_FORMAT(iterDateTime, '%Y-%m-%d'), DATE_FORMAT(iterDateTime, '%H:%i:%s') );
SET iterDateTime = ADDTIME(iterDateTime , '1:0:0');
END WHILE;
SET iterDate = ADDTIME(iterDate , '1 0:0:0');
END WHILE ;
SELECT * FROM tempNextWeek;
-- drop table if exists tempNextWeek;
END;;
DELIMITER ;
CALL ListHours();
I have 2days like check_in(25/04/2011), and a check_out(04/06/2011). Now I need to calculate the days between the dates in month wise.
ie. Month - Days,
April - 5,
May - 31,
June - 4,
Please help me in building as mysql query for getting the above result.
Thanks in advance.
If you want strictly done in MySQL, you need to create a Stored Procedure to do this.
Something like this in line of Stored Procedure (and range is not higher than a year).
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;
call like this:
set max_sp_recursion_depth = 11;
call getDateDiffBreakdown('2011-12-11','2012-06-03');
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 was trying to solve the problem too.
Pentium10 is too strong and now I'll try his solution. :)
By the way this is mine.
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)
Hope that it helps.
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;
Use TO_DAYS(date) function for that.