Calculate month difference based on dates SQL Server 2008 R2 - sql-server-2008-r2

I would like to calculate the difference between two dates in months.
The problem:
SELECT DATEDIFF(mm, '2015-11-01', '2015-11-30')
The date difference returns 0. I want to display 1 instead. If the difference is more than 15 days then it should round to next month.
I tried using round and ceiling functions and division by 30, but it still doesn't give me the desired result.
Reason this question is different from "possible duplicate" is because I am looking for only month calculation based on Start and End date. Also, my Start and End date structure is beginning of a month and end of a month instead of exact dates.

Try this:
SELECT DATEDIFF(mm, '2015-11-01', '2015-11-30')
+ CASE WHEN (DATEDIFF(mm, '2015-11-01', '2015-11-30') = 0 and DATEDIFF(dd, '2015-11-01', '2015-11-30') > 15) THEN 1 ELSE 0 END CASE

Try this.
Select
DATEDIFF(mm, '2015-11-01', '2015-11-30')
+ CASE WHEN abs(DATEPART(day, '2015-11-01') - DATEPART(day, '2015-11-30')) > 15 THEN 1 ELSE 0 END

Related

How can I adapt an existing query to only count working days?

I need to adapt the below query so that the measurements between date1 and date2 only counts working days (Monday-Friday), and exclude the weekends.
select [other columns], date_part('day', Min(date1) - date2) as days_to_open
from X
where [...]
group by [...]
I've looked up many answers but I don't understand how to put them within an existing query like the one above.
I'm not an experienced user so apologies if this is trivial. Using postgresql.
select [other columns], date_part('day', Min(date1) - date2 + (sum(CASE extract(DOW from date2)::int % 6 WHEN 0 THEN 1 ELSE 0 END )||' day')::interval ) as days_to_open
from X
where [...]
group by [...]
This use of sum(), cast as an interval of days, tells the query to add back in the number of Saturdays and Sundays over the difference in dates. The dow datepart is "day-of-week", which is 0 for Sundays and 6 for Saturdays, meaning that weekends are defined by the dow modulo 6 equalling zero.

DB2: Bi-monthly query for a DB2 report

I am currently writing a Crystal Report that has a DB2 query as its backend. I have finished the query but am stuck on the date portion of it. I am going to be running it twice a month - once on the 16th, and once on the 1st of the next month. Here's how it should work:
If I run it on the 16th of the month, it will give me results from the 1st of that same month to the 15th of that month.
If I run it on the 1st of the next month, it will give me results from the 16th of the previous month to the last day of the previous month.
This comes down a basic bi-monthly report. I've found plenty of hints to do this in T-SQL, but no efficient ways on how to accomplish this in DB2. I'm having a hard time wrapping my head around the logic to get this to consistently work, taking into account differences in month lengths and such.
There are 2 expressions for start and end date of an interval depending on the report date passed, which you may use in your where clause.
The logic is as follows:
1) If the report date is the 1-st day of a month, then:
DATE_START is 16-th of the previous month
DATE_END is the last day of the previous month
2) Otherwise:
DATE_START is 1-st of the current month
DATE_END is 15-th of the current month
SELECT
REPORT_DATE
, CASE DAY(REPORT_DATE) WHEN 1 THEN REPORT_DATE - 1 MONTH + 15 ELSE REPORT_DATE - DAY(REPORT_DATE) + 1 END AS DATE_START
, CASE DAY(REPORT_DATE) WHEN 1 THEN REPORT_DATE - 1 ELSE REPORT_DATE - DAY(REPORT_DATE) + 15 END AS DATE_END
FROM
(
VALUES
DATE('2020-02-01')
, DATE('2020-02-05')
, DATE('2020-02-16')
) T (REPORT_DATE);
The result is:
|REPORT_DATE|DATE_START|DATE_END |
|-----------|----------|----------|
|2020-02-01 |2020-01-16|2020-01-31|
|2020-02-05 |2020-02-01|2020-02-15|
|2020-02-16 |2020-02-01|2020-02-15|
In Db2 (for Unix, Linux and Windows) it could be a WHERE Condition like
WHERE
(CASE WHEN date_part('days', CURRENT date) > 15 THEN yourdatecolum >= this_month(CURRENT date) AND yourdatecolum < this_month(CURRENT date) + 15 days
ELSE yourdatecolum > this_month(CURRENT date) - 1 month + 15 DAYS AND yourdatecolum < this_month(CURRENT date)
END)
Check out the THIS_MONTH function - there are multiple ways to do it. Also DAYS_TO_END_OF_MONTH might be helpful

PostgreSQL Selecting The Closest Previous Month of June

I am trying to write a piece for a query that grabs the closest, past June 1st. For example, today is 10/2/2018. If I run the query today, I need it to use the date 6/1/2018. If I run it on 5/29/2019, it still needs to grab 6/1/2018. If I run it on 6/2/2019, it should then grab 6/1/2019. If I run it on 6/2/2022, it should then grab 6/1/2022 and so on.
I believe I need to start with something like this:
SELECT CASE WHEN EXTRACT(MONTH FROM NOW())>=6 THEN 'CURRENT' ELSE 'RF LAST' END AS X
--If month is greater than or equal to 6, you are in the CURRENT YEAR (7/1/CURRENT YEAR)
--If month is less than 6, then reference back to the last year (YEAR MINUS ONE)
And I believe I need to truncate the date then perform an operation. I am unsure of which approach to take (if I should be adding a year to a timestamp such as '6/1/1900', or if I should try to disassemble the date parts to perform an operation. I keep getting errors in my attempts such as "operator does not exist". Things I have tried include:
SELECT (CURRENT_DATE- (CURRENT_DATE-INTERVAL '7 months'))
--This does not work as it just gives me a count of days.
SELECT (DATE_TRUNC('month',NOW())+TIMESTAMP'1900-01-01 00:00:00')
--Variations of this just don't work and generally error out.
Use a case expression to determine if you need to use the current year, or, the previous year (months 1 to 5)
case when extract(month from current_date) >= 6 then 0 else -1 end
then add that to the year extracted from current_date, e.g. using to_date()
select to_Date('06' || (extract(year from current_date)::int + case when extract(month from current_date) >= 6 then 0 else -1 end)::varchar, 'mmYYYY');
You could also use make_date(year int, month int, day int) in postgres 9.4+
select make_date(extract(year from current_date) + case when extract(month from current_date) >= 6 then 0 else -1 end, 6, 1) ;
If month lower than 6, trunc year and minus 6 months.
Else trunc year and add 6 months.
set datestyle to SQL,MDY;
select
case when (extract( month from (date::date)))<6 then date_trunc('year',date)-'6 month'::interval
else date_trunc('year',date)+'6 months'::interval
end as closest_prev_june,
another_column,
another_column2
from mytable;
But format is default and supposed you have a column that named date.
If you want to do this with now(), change date columns with now()
function.

Get difference between two dates in Years

I am working with a table that has StartDate and EndDate fields. I need to find difference between then in years.
Example:
StartDate = 1/1/2017
EndDate = 12/31/2017
I expect Result = 1 for the date difference.
Also, I'd like to round it to nearest whole number.
Example:
StartDate = 1/1/2017
EndDate = 11/30/2017
I expect Result = 1 for the date difference.
Using datediff function, I am able to get the result, but it isn't rounding to nearest whole number.
Example query:
I am getting 6 years even though 65 months / 12 would be less than 5.5:
select (DATEDIFF(yy, '01/01/2016', '5/31/2021')
+ CASE WHEN abs(DATEPART(day, '01/01/2016') - DATEPART(day, '05/31/2021')) > 15 THEN 1 ELSE 0 END)
select (DATEDIFF(mm, '01/01/2016', '05/31/2021')
+ CASE WHEN abs(DATEPART(day, '01/01/2016') - DATEPART(day, '05/31/2021')) > 15 THEN 1 ELSE 0 END)
DECLARE #startdate DATETIME = '1-1-2017',
#enddate DATETIME = '12-31-2018'
SELECT #startdate as StartDate, #enddate as EndDate,
DATEDIFF(YEAR, #startdate, #enddate)
-
(CASE
WHEN DATEADD(YEAR,
DATEDIFF(YEAR, #startdate,#enddate), #startdate)
> #enddate THEN 1
ELSE 0 END) 'Date difference in Years'
Use this code, I hope it will help you.
So far following query seems to be working okay. My mistake was I dividing by 12 instead of 12.0 for rounding to work correctly. Who knew! :
select
Round((DATEDIFF(mm, '01/01/2016', '07/1/2017')
+ CASE WHEN abs(DATEPART(day, '01/01/2016') - DATEPART(day, '06/30/2017')) > 15 THEN 1 ELSE 0 END) / 12.0, 0)
This may be a bit old but when using Oracle SQL Developer you can use the following. Just add your Dates below. I was using DateTime. This was used to get years between 0 and 10.
TRUNC((MONTHS_BETWEEN(<DATE_ONE>, <DATE_TWO>) * 31) / 365) > 0 and TRUNC((MONTHS_BETWEEN(<DATE_ONE>, <DATE_TWO>) * 31) / 365) < 10

Using TSQL to find variance in minutes between two dates where seconds portion is greater than zero

Need some help to verify this is the correct way of obtaining the result.
I need to find the variance in minutes between two dates where the seconds
portion of the date > 0.
List for the past minute, Variance = (Event_BeginTime - Event_CreateDate) where the seconds portion of HH:MM:SS > 0
SELECT Event_BeginTime
,Event_CreateDate
,DATEDIFF(MINUTE,Event_BeginTime,Event_CreateDate) AS 'Variance'
FROM Events WITH (NOLOCK)
WHERE RIGHT(CAST(Event_BeginTime AS TIME(0)), 2) > 0 AND Event_CreateDate >= DATEADD(MINUTE, -1, GETDATE())
ORDER BY Event_CreateDate DESC
You can use VAR:
VAR(DATEDIFF(MINUTE,Event_BeginTime,Event_CreateDate))
As for the date I would use DATEPART:
DATEPART ( SS, date )