How to calculate days between two dates, - mysql

Is it possible in MySQL to easily to get the number of days between two dates, group by months and then disperse those days between the months, so that when I group by month, I get to see how many days inbetween two those two dates fall into each month.
Example: creation 05.05.2014 to expiration 06.06.2014 returns 32 days. I want to display this as:
May: 26 days
June: 5 days
So far I've got:
SELECT MONTHNAME(date) as month_name,
SUM(DATEDIFF(expiration, date)) AS num_days
FROM reservations
GROUP BY month_name
But it doesn't disperse the days corretly by month, just drop them all into the group-by -start-date-month, obviously. Any ideas would be highly appriciated.

I would build a comprehensive date temp table (or CTE) first.
From there you can select what you'd like, and group it however suits your needs.
IF OBJECT_ID('TEMPDB..#Dates') IS NOT NULL DROP TABLE #Dates
DECLARE #StartDate DATETIME, #EndDate DATETIME
SET #StartDate = '05/05/2014'
SET #EndDate = '06/06/2014'
;WITH Dates AS
(
SELECT CAST(CONVERT(VARCHAR(8), #StartDate,112) AS INT) AS DateId
, CAST(#StartDate AS DATE) AS Date
, CAST(#StartDate AS DATETIME) AS DateTime
, DATEPART(QUARTER, #StartDate) AS QuarterId
, 'Q' + CAST(DATEPART(QUARTER,#StartDate) AS CHAR(1)) AS Quarter
, DATEPART(MONTH, #StartDate) AS MonthId
, DATENAME(MONTH, #StartDate) AS Month
, DATEPART(DAY, #StartDate) AS Day
, DATEPART(YEAR, #StartDate) AS Year
, DATENAME(DW,#StartDate) AS DayOfWeek
, DATEPART(DAYOFYEAR, #StartDate) AS DayOfYear
UNION ALL
SELECT CAST(CONVERT(VARCHAR(8),DATEADD(DAY, 1, D.DateTime), 112) AS INT) ASDateId
, CAST(DATEADD(DAY, 1, D.DateTime) AS DATE) AS Date
, CAST(DATEADD(DAY, 1, D.DateTime) AS DATETIME) AS DateTime
, DATEPART(QUARTER,DATEADD(DAY,1,D.DateTime)) AS QuarterId
,'Q'+CAST(DATEPART(QUARTER,DATEADD(DAY, 1, D.DateTime)) AS CHAR(1)) AS Quarter
, DATEPART(MONTH,DATEADD(DAY, 1, D.DateTime)) AS MonthId
, DATENAME(MONTH,DATEADD(DAY, 1,D.DateTime)) AS Month
, DATEPART(DAY,DATEADD(DAY, 1, D.DateTime)) AS Day
, DATEPART(YEAR,DATEADD(DAY, 1, D.DateTime)) AS Year
, DATENAME(DW,DATEADD(DAY,1, D.DateTime)) AS DayOfWeek
, DATEPART(DAYOFYEAR,DATEADD(DAY,1, D.DateTime)) AS DayOfYear
FROM Dates AS D
WHERE D.DateTime < #EndDate
)
SELECT DateId AS DateId
, Date AS Date
, DateTime AS DateTime
, QuarterId AS QuarterId
, Quarter AS Quarter
, MonthId AS MonthId
, Month AS Month
, Day AS Day
, Year AS Year
, DayOfWeek AS DayOfWeek
, DayOfYear AS DayOfYear
, ROW_NUMBER() OVER(ORDER BY DateId)-1 AS DayCount
INTO #Dates
FROM Dates AS D
ORDER BY D.DateId
OPTION (MAXRECURSION 32767)
-- SELECT * FROM #Dates
SELECT COUNT(Day) AS CountOfDays, Month
FROM #Dates
GROUP BY Month

Related

Return Monthly Data From Query Even When Month Does Not Exist In DataSet

I am a MS SQL Server guy, but am having to write some MySQL Queries. I am attempting to write a query that will show monthly sales data for a selected employee and if the employee has no sales data for that month show the month and a 0.
This is the query I have but it's returning NULL?
CREATE TABLE `saleamountbyemployee` (
`month_year` varchar(9) DEFAULT NULL,
`total_sales` int(11) NOT NULL,
`employee` char(17) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `saleamountbyemployee` (`month_year`,`total_sales`,`employee`) VALUES ('Feb 18','34512','James Jones');
INSERT INTO `saleamountbyemployee` (`month_year`,`total_sales`,`employee`) VALUES ('Feb 18','223','Sally Smith');
INSERT INTO `saleamountbyemployee` (`month_year`,`total_sales`,`employee`) VALUES ('Feb 18','22','James Jones');
WITH RECURSIVE
cte_months_to_pull AS (
SELECT DATE_FORMAT(#start_date, '%Y-%m-01') - INTERVAL #number_of_months MONTH AS month_to_pull
UNION ALL
SELECT month_to_pull + INTERVAL 1 MONTH
FROM cte_months_to_pull
WHERE month_to_pull < #start_date + INTERVAL #number_of_months - 2 MONTH
)
SELECT YRS.months_to_pull,T.employee,COALESCE(T.IA, 0) IA
FROM (SELECT DATE_Format(month_to_pull, '%b-%Y') months_to_pull
FROM cte_months_to_pull
ORDER BY months_to_pull
) AS YRS
LEFT JOIN (SELECT Date_format(month_year, '%b-%Y') AS `Month`
,employee,Sum(total_sales) AS IA
FROM saleamountbyemployee
WHERE employee = 'James Jones'
GROUP BY Date_format(month_year, '%b-%Y'), employee) T
ON YRS.months_to_pull = T.`Month`
order by month(STR_TO_DATE(CONCAT('01-',months_to_pull), '%d-%b-%Y')),YEAR(STR_TO_DATE(CONCAT('01-',months_to_pull), '%d-%b-%Y'))
EDIT
If I alter syntax to this:
SET #start_date = 'Jan 18';
SET #number_of_months = 12;
WITH RECURSIVE
cte_months_to_pull AS (
SELECT str_to_date(CONCAT(#start_date,' 01'), '%b %y %d') - INTERVAL #number_of_months MONTH AS month_to_pull
UNION ALL
SELECT month_to_pull + INTERVAL 1 MONTH
FROM cte_months_to_pull
WHERE month_to_pull < #start_date + INTERVAL #number_of_months - 2 MONTH
)
SELECT YRS.months_to_pull,T.employee,COALESCE(T.IA, 0) IA
FROM (SELECT DATE_Format(month_to_pull, '%b-%Y') months_to_pull
FROM cte_months_to_pull
ORDER BY months_to_pull
) AS YRS
LEFT JOIN (SELECT Date_format(month_year, '%b-%Y') AS `Month`
,employee,Sum(total_sales) AS IA
FROM saleamountbyemployee
WHERE employee = 'James Jones'
GROUP BY Date_format(month_year, '%b-%Y'), employee) T
ON YRS.months_to_pull = T.`Month`
order by month(STR_TO_DATE(CONCAT('01-',months_to_pull), '%d-%b-%Y')),YEAR(STR_TO_DATE(CONCAT('01-',months_to_pull), '%d-%b-%Y'))
I now get this error message:
Error Code: 1292. Incorrect datetime value: 'Jan 18'
This line in the CTE:
SELECT DATE_FORMAT(#start_date, '%Y-%m-01') - INTERVAL #number_of_months MONTH AS month_to_pull
The date format of '%Y-%m-01' doesn't match what's in the table. If you use 'Feb 18' as the value of the #start_date parameter, it will return NULL. The date_format you specified expects it to look like this:
SELECT DATE_FORMAT('2018-01-01', '%Y-%m-01') - INTERVAL 1 MONTH AS month_to_pull
Add ' 01' to the date, this will make it think it's the first of the month.
SELECT str_to_date(CONCAT(#start_date,' 01'), '%b %y %d') - INTERVAL #number_of_months MONTH AS month_to_pull
This will return the following if you use 'Feb 18' as the #start_date and 1 as the #number_of_months:
1/1/2018 12:00:00 AM
That VARCHAR data type and date format in the table is gonna bite you.
I am attempting to write a query that will show monthly sales data for a selected employee and if the employee has no sales data for that month show the month and a 0.
Assuming that you have data for some employee in each month, you can use conditional aggregation:
select month_year,
sum(case when employee = 'James Jones' then total_sales else 0 end) as monthly_sales
from saleamountbyemployee sae
group by month_year;

SQL select date range by month and year

How do I select date range from this query?
E.g : From Month('2017-05-22') And Year(date1) = Year('2017-05-22')
to Month('2018-05-22') And Year(date1) = Year('2018-05-22')
My current query :
SELECT
date1
FROM
data
WHERE
Month(date1) = Month('2018-05-22') And Year(date1) = Year('2018-05-22')
I'd convert those literals to dates using str_to_date:
SELECT MONTH(date1)
FROM data
WHERE date1 BETWEEN STR_TO_DATE('2017-05-22', '%Y-%m-%d') AND STR_TO_DATE('2018-05-23', '%Y-%m-%d')
Note that between is inclusive on the first argument and exclusive on the second, so I bumped the day to the 23rd.
BETWEEN condition to retrieve values within a date range.
For example:
SELECT *
FROM order_details
WHERE order_date BETWEEN CAST('2014-02-01' AS DATE) AND CAST('2014-02-28' AS DATE);
This MySQL BETWEEN condition example would return all records from the order_details table where the order_date is between Feb 1, 2014 and Feb 28, 2014 (inclusive). It would be equivalent to the following SELECT statement:
SELECT *
FROM order_details
WHERE order_date >= CAST('2014-02-01' AS DATE)
AND order_date <= CAST('2014-02-28' AS DATE);
SELECT TO_CHAR(systemts, 'yyyy-mm') as yyyymm,
max(notenum) - min(notenum) + 1 as notenum_range
FROM your_table_name
WHERE systemts >= to_date('2018-01-01', 'yyyy-mm-dd') AND
systemts < to_date('2018-07-17', 'yyyy-mm-dd')
GROUP BY TO_CHAR(systemts, 'yyyy-mm');
DECLARE #monthfrom int=null,
#yearfrom int=null,
#monthto int=null,
#yearto int=null
/**Region For Create Date on Behalf of Month & Year**/
DECLARE #FromDate DATE=NULL
DECLARE #ToDate DATE=NULL
SET #FromDate=DateAdd(day,0, DateAdd(month, #monthfrom - 1,DateAdd(Year, #yearfrom-1900, 0)))
SET #ToDate=DateAdd(day,-1, DateAdd(month, #monthto - 0,DateAdd(Year, #yearto-1900, 0)))
/**Region For Create Date on Behalf of Month & Year**/
SELECT DISTINCT month ,Year FROM tbl_Att
WHERE (DATEADD(yy, year - 1900, DATEADD(m, Month - 1, 1 - 1)) BETWEEN CONVERT(DATETIME, #FromDate, 102) AND
CONVERT(DATETIME, #ToDate, 102))

How to get date range from week number in sql

I would like to get date range from week number in sql.
eg .
select datepart(week,GETDATE()) // 37
I want to get dates from week 37(4/09/2016 , 05/09/2016 , 06/09/2016 , 07/09/2016 , 08/09/2016 , 09/09/2016 , 10/09/2016)
Try this,
DECLARE #StartDate DATE = dateadd(day, 1-datepart(dw, getdate()), CONVERT(date,getdate()))
, #EndDate DATE = dateadd(day, 7-datepart(dw, getdate()), CONVERT(date,getdate()))
SELECT DATEADD(DAY, nbr - 1, #StartDate) as CurrentWeekDates
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
FROM sys.columns c
) nbrs
WHERE nbr - 1 <= DATEDIFF(DAY, #StartDate, #EndDate)

select every 4th saturday from a set date sql

I am trying to write a SQL statement that selects every 4th Saturday from a set date. So if the date chosen is 07/09/2014 then the query would return 05/10/2014 and 02/11/2014 and so on.
I can get it to select every Saturday going forward from the date but I can not work out how to get it to work out the 4th one each time.
SELECT DATE
, DATENAME(DW,DATE) as Date
FROM tblCalender
WHERE DATENAME(DW,DATE) = 'Saturday'
AND Date > '13-September-2014'
This is the select to get the saturdays going forward.
Sussed it thanks to t_m suggestion
DECLARE #Date DATETIME
SET #Date = '19-July-2014'
SELECT Date AS SatDate
, DayOfWeek
FROM (
SELECT DATE
, DATENAME(DW,DATE) as DayOfWeek
, ROW_NUMBER() OVER (ORDER BY Date) AS rownum
FROM tblCalender
WHERE DATENAME(DW,DATE) = 'Saturday'
AND Date > #Date
) AS t
WHERE t.rownum % 4 = 0
Thanks for the tip!

How to add hours to current date in SQL Server?

I am trying to add hours to current time like
-- NOT A VALID STATEMENT
-- SELECT GetDate(DATEADD (Day, 5, GETDATE()))
How can I get hours ahead time in SQL Server?
DATEADD (datepart , number , date )
declare #num_hours int;
set #num_hours = 5;
select dateadd(HOUR, #num_hours, getdate()) as time_added,
getdate() as curr_date
Select JoiningDate ,Dateadd (day , 30 , JoiningDate)
from Emp
Select JoiningDate ,DateAdd (month , 10 , JoiningDate)
from Emp
Select JoiningDate ,DateAdd (year , 10 , JoiningDate )
from Emp
Select DateAdd(Hour, 10 , JoiningDate )
from emp
Select dateadd (hour , 10 , getdate()), getdate()
Select dateadd (hour , 10 , joiningDate)
from Emp
Select DateAdd (Second , 120 , JoiningDate ) , JoiningDate
From EMP
The DATEADD() function adds or subtracts a specified time interval from a date.
DATEADD(datepart,number,date)
datepart(interval) can be hour, second, day, year, quarter, week etc;
number (increment int);
date(expression smalldatetime)
For example if you want to add 30 days to current date you can use something like this
select dateadd(dd, 30, getdate())
To Substract 30 days from current date
select dateadd(dd, -30, getdate())
declare #hours int = 5;
select dateadd(hour,#hours,getdate())
SELECT GETDATE() + (hours / 24.00000000000000000)
Adding to GETDATE() defaults to additional days, but it will also convert down to hours/seconds/milliseconds using decimal.
If you are using mySql or similar SQL engines then you can use the DATEADD method to add hour, date, month, year to a date.
select dateadd(hour, 5, now());
If you are using postgreSQL you can use the interval option to add values to the date.
select now() + interval '1 hour';