I have to calculate a date field in run time based on 2 other fields.
----------------------------------------------------------
Run Date || Schedule || Next Bill run date
-----------------------------[enter image description here][1]-----------------------------
----------------------------------------------------------
11/29/2018 || 1st || 12/01/2018
----------------------------------------------------------
11/29/2018 || 15th || 12/15/2018
----------------------------------------------------------
12/02/2018 || 1st || 12/01/2019
----------------------------------------------------------
12/02/2018 || 15th || 12/15/2018
----------------------------------------------------------
12/16/2018 || 15th || 01/15/2019
----------------------------------------------------------
In the above scenario Next bill Run date should be populated based on the previous 2 column.
There are 4 conditions are there,
if the day(Run_date) between 2nd-15th of the same month and value of schedule is '15th' then "Next Bill Run" will be 15th of the same month.
if the day(Run_date) between 16th(same month) - 1st(next month) and value of schedule is '15th' then "Next Bill Run" will be 15th of the next month.
if the day(Run_date) between 2nd-15th of the same month and value of schedule is '1st' then "Next Bill Run" will be 1st of the next month.
if the day(Run_date) between 16th(same month) - 1st(next month) and value of schedule is '1st' then "Next Bill Run" will be 1st of the next month.
Please see the above table for better understanding. Please help me to find out a logic to implement "Next Bill Run". Appreciate your help.
I am thinking of using 'case' function to get the datepart() of the Run Date. But still confused with the implementation
Hope this below query will help you.
set #lastDate := (SELECT LAST_DAY(now()) AS first_day);
set #firstDate := (SELECT DATE_ADD(DATE_ADD(LAST_DAY(now()),INTERVAL 1 DAY),INTERVAL - 1 MONTH) AS first_day);
select run_date,schedule,
case
when run_date between #firstDate and DATE_ADD(#firstDate, INTERVAL 14 DAY) and schedule ='15th' then DATE_ADD(#firstDate, INTERVAL 14 DAY)
when run_date between DATE_ADD(#firstDate, INTERVAL 15 DAY) and DATE_ADD(#firstDate, INTERVAL 1 MONTH) and schedule ='15th' then date_add(DATE_ADD(#firstDate, INTERVAL 14 DAY), INTERVAL 1 MONTH)
when run_date between #firstDate and DATE_ADD(#firstDate, INTERVAL 14 DAY) and schedule ='1st' then DATE_ADD(#firstDate, INTERVAL 1 MONTH)
when run_date between DATE_ADD(#firstDate, INTERVAL 15 DAY) and DATE_ADD(#firstDate, INTERVAL 1 MONTH) and schedule ='1st' then DATE_ADD(#firstDate, INTERVAL 1 MONTH)
end
as next_bill_run_date
from your_table
in SQL Server
declare #firstDate as date = '01-'+month(getdate())+'-'+year(getdate());
select run_date,schedule,
case
when run_date between #firstDate and DATEADD(DAY,14,#firstDate) and schedule ='15th' then DATEADD(DAY,14,#firstDate)
when run_date between DATEADD(DAY,15,#firstDate) and DATEADD(MONTH, 1, #firstDate) and schedule ='15th' then DATEADD(MONTH, 1, DATEADD(DAY,14,#firstDate))
when run_date between DATEADD(DAY,14,#firstDate) and schedule ='1st' then DATEADD(MONTH, 1, #firstDate)
when run_date between DATEADD(DAY,15,#firstDate) and DATEADD(MONTH, 1 #firstDate) and schedule ='1st' then DATEADD(MONTH, 1 #firstDate)
end
as next_bill_run_date
from your_table
Yes, your logic is correct. Use the case statement along with some of the DATE functions in SQL SERVER. With my limited knowledge with SQL SERVER date functions i have framed the below query. You can still optimize this.
SELECT
RUN_DATE,SCHEDULE,
case
when (DATEPART(month,run_date)=month(sysdatetime()) --checking same month
and DATEPART(day, run_date) between 2 and 15 and Schedule='15th') --checking date between 2nd and 15th and schedule is 15th
then DATEADD(month, DATEDIFF(month, 0,run_date), 0)+14 --selecting 15th of same month
when (DATEPART(month,run_date)=month(sysdatetime())
and DATEPART(day, run_date) between 2 and 15 and Schedule='1st') --checking date between 2nd and 15th and schedule is 1st
then DATEADD(month, DATEDIFF(month, 0,run_date)+1, 0) --selecting 1st of next month
when (DATEPART(month,run_date)=month(sysdatetime()) or run_date=DATEADD(month, DATEDIFF(month, 0,run_date)+1,0))
and (((DATEPART(day, run_date) between 16 and 31) or (run_date=DATEADD(month, DATEDIFF(month, 0,run_date)+1,0)))
and Schedule='1st')
then case when (run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0))
then
DATEADD(month, DATEDIFF(month, 0,run_date),0) -- if 1st of next month, select first day of same month
else
DATEADD(month, DATEDIFF(month, 0,run_date)+1,0) --selecting 1st of next month
end
when (DATEPART(month,run_date)=month(sysdatetime()) or run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0))
and (((DATEPART(day, run_date) between 16 and 31) or (run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0)))
and Schedule='15th')
then case when (run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0))
then
DATEADD(month, DATEDIFF(month, 0,run_date),0)+14 -- if 1st of next month, select 15 of same month
else
DATEADD(month, DATEDIFF(month, 0,run_date)+1,0)+14 --selecting 15th of next month
end
end as NEXT_BILL_RUN_DATE
FROM mytable ;
case
when schedule='1st'
then DATEFROMPARTS(DATEPART(year, DATEADD(month, 1, RUN_DATE)), DATEPART(month, DATEADD(month, 1, RUN_DATE)), 01)
when schedule='15th' and DATEPART(day, RUN_DATE)>=15
then DATEFROMPARTS(DATEPART(year, DATEADD(month, 1, RUN_DATE)), DATEPART(month, DATEADD(month, 1,RUN_DATE)), 15)
when schedule='15th' and DATEPART(day, RUN_DATE)<15
then DATEFROMPARTS(DATEPART(year, RUN_DATE), DATEPART(month, RUN_DATE)), 15)
end AS NEXT_BILL_RUN_DATE
Related
This is my query
select *
from RDR1 A
where Year(A.shipdate) = '2021'
and (
Month(A.shipdate) = Month(CURRENT_TIMESTAMP) - 1
or Month(A.shipdate) = Month(CURRENT_TIMESTAMP) + 1
or Month(A.shipdate) = Month(CURRENT_TIMESTAMP)
)
The above query works fine when they choose the year 2020, But when they choose 2021 it doesn't work. The above query should filter based on the current month. For eg: December 2020 (Current Month), Jan 2021 (next month), November (Previous Month).
How should I modify my query?
If you want the last month, this month, or next month, I would suggest:
where a.shipdate >= dateadd(month, -1, datefromparts(year(getdate()), month(getdate()), 1)) and
a.shipdate < dateadd(month, 2, datefromparts(year(getdate()), month(getdate()), 1))
This is index-friendly. If that is not a concern, you can use:
where datediff(month, s.shipdate, getdate()) between -1 and 1
How can I select
The past week
Its corresponding days in the year before
This is needed for a dashboard, I would like to show a chart with results from the past seven days. It displays green if our call-center handles 98% of their phone calls within a certain time-span, red if we go over 98%. As a reference I would like to create a chart below with the corresponding seven days in the year before. This is challenging, because weekdays really influence the workload. That means I can't compare a Tuesday with a Sunday or Monday.
For instance, today is Saturday 21st Dec 2019, I would like to report the following timespans:
2019-12-13 00:00:00 -> 2019-12-20 23:59:59
and
2018-12-14 00:00:00 -> 2018-12-21 23:59:59
I made the following code (used within a select statement):
case when cs.ReachedAt between (getdate() - 7) and getdate() then 1 else 0 end as Is_PastWeek
case when cs.ReachedAt between (convert(datetime, convert(varchar(50), convert(date, dateadd(d, -1, dateadd(wk, -52, getdate())))) + ' 23:59:59')) and (convert(datetime, convert(varchar(50), convert(date, dateadd(d, -8, dateadd(wk, -52, getdate())))) + ' 00:00:00')) then 1 else 0 end as Is_SameWeekLastYear
It works, but isn't perfect. I just select the corresponding weekday in the same week as 52 weeks ago. Which means I sometimes end up selecting a matching weekday, but not the nearest. How can I do this better?
EDIT
To clarify what I mean by "picking the nearest corresponding weekday in the year before", i made the following example:
with cte1 as (
select row_number() over (order by (select 1)) - 1 as incrementor
from master.sys.columns sc1
cross join master.sys.columns sc2
), cte2 as (
select dateadd(day, cte1.incrementor, '2000-01-01') as generated_date
from cte1
where dateadd(day, cte1.incrementor, '2000-01-01') < getdate()
), cte3 as (
select convert(date, generated_date) as generated_date
, convert(date, getdate()) as now_date
from cte2
), cte4 as (
select *
, convert(date, dateadd(YEAR, -1, now_date)) as year_back
from cte3
)
select now_date
, generated_date
from cte4
where 1=1
and datepart(week, year_back) = datepart(week, generated_date)
and datepart(DW, year_back) = datepart(DW, generated_date)
This will result in:
For the grey values, I would rather take the weekday of one week later. That way I pick "the nearest corresponding weekday in the year before".
Please note that the above is an example to show what I mean, my ultimate goal is to start with this date, select the whole week before... And all (if possible) neatly within a where clause.
The expression datepart(week, getdate()) will deliver you the calendar week. With this, you can go further.
This is too long for a comment.
What difference does it make? If you are looking for the past week, just look at the same 7 days from the previous year. In one case the week might start on a Tuesday and in the other on a Wednesday. But in both cases, each weekday occurs once.
The logic would be:
where cs.ReachedAt >= datefromparts(year(getdate() - 7) - 1, month(getdate() - 7), day(getdate() - 7) and
cs.ReachedAt < datefromparts(year(getdate()), month(getdate()), day(getdate()))
The logic for the current year:
where cs.ReachedAt >= convert(date, getdate() - 7) and
cs.ReachedAt < convert(date, getdate())
I am trying to get the First Date of the current Fiscal year. In my case the Fiscal year starts in Oct.
Example: I need the 10/01/2015
I would generally use the below query to the get the first day of the current year but how do I change it to get the first date of fiscal year?
select
convert(varchar(12), (
DateAdd(month, (
Month(getdate()) - 1) * -1,
DateAdd(Day, (
Day(getdate()) - 1) * -1,
getdate()))),
103) as StartYear
You can apply following logic: Subtract 9 months from the current date, find Jan 1st of this year and add 9 months again:
DATEADD(MONTH, 9, DATEADD(YEAR, DATEDIFF(YEAR, 0, DATEADD(MONTH, -9, GETDATE())), 0))
declare #fiscal date = '2015-10-01'
; with dates
as
(
select date = '2015-09-30' union all
select date = '2015-10-01' union all
select date = '2016-09-30' union all
select date = '2016-10-01'
)
select *,
fiscal = case when date < dateadd(year, year(date) - year(#fiscal), #fiscal)
then dateadd(year, year(date) - year(#fiscal) - 1, #fiscal)
else dateadd(year, year(date) - year(#fiscal), #fiscal)
end
from dates
/* result
date fiscal
---------- ----------
2015-09-30 2014-10-01
2015-10-01 2015-10-01
2016-09-30 2015-10-01
2016-10-01 2016-10-01
*/
At first Subtract 9 months from current date to get the previous year(your Fasical year).
Then take the year difference with 0 to your date.
Now add the year difference with 0 to get the starting of a month.
Finally you need to add the 9 months to get the starting month of a Fasical Year.
As year example the require format "10/01/2015". So get that you can use convert function with 101.
select convert(varchar(12), DATEADD(MONTH, 9, DATEADD(YEAR, DATEDIFF(YEAR, 0, DATEADD(MONTH, -9, GETDATE())), 0)), 101) as StartYear
I'm hoping to find a solution for this to automate a report I have. Basically what I'm trying to accomplish here is grabbing a date (first day of previous month, two years ago through last day of previous month current year).
So the date span if running this month would look like this: between 4/1/2013 and 3/31/2015
I have found code to get the date two years ago but I'm not able to also incorporate the month functions... Any help is very much appreciated!
For year I'm using this:
SELECT CONVERT(VARCHAR(25),DATEADD(year,-2,GETDATE()),101)
First day of previous month 2 years ago:
SELECT CONVERT(DATE,dateadd(day, -1, dateadd(day, 1 - day(GETDATE()), GETDATE())))
Last day of last month:
SELECT CONVERT(DATE,DATEADD(month, DATEDIFF(month, 0, DATEADD(year,-2,GETDATE())), 0))
Then just do whatever logic you need with them
Your where clause can look something like this:
where date >= cast(dateadd(year, -2,
dateadd(month, -1, getdate() - day(getdate()) + 1)
) as date) and
date < cast(getdate() - day(getdate()) + 1 as date)
This makes use of the handy convenience that subtracting/adding a number to a datetime is the same as adding a date. The start date says: get the first day of the month, then subtract one month, then subtract two years. This could have been done as dateadd(month, -25, . . .), but I think separating the logic is clearer.
This gives you two dates you are looking for:
SELECT
CAST((DATEADD(yy, -2, DATEADD(d, -1 * DATEPART(dd, getdate()) + 1 , GETDATE() ))) as date) as yourTwoYearsAgoDate,
CAST((DATEADD(d, -1 * DATEPART(dd, GETDATE()), GETDATE())) as date) as yourEndOfLastMonthDate
Given a reference date (e.g. "today"),
declare #today date = '23 April 2015'
The 1st of the month is computed by subtracting 1 less than the day number of the current month:
select first_of_current_month = dateadd(day,1-day(#today),#today)
The last day of the previous month is day 0 of the current month, so to get the last day of the previous month, just subtract the current day number:
select last_of_previous_month = dateadd(day,-day(#today),#today)
Moving two years back is easy:
select two_years_back = dateadd(year,-2, #today )
Putting it all together, this should do you:
declare #today date = '23 April 2015'
select *
first_day_of_current_month = dateadd(day,1-day(#today),#today),
last_day_of_previous_month = dateadd(day, -day(#today),#today) ,
date_from = dateadd(year,-2, dateadd(day,1-day(#today),#today) ) ,
date_thru = dateadd(day, -day(#today),#today)
yielding the expected results:
first_day_of_current_month: 2015-04-01
last_day_of_previous_month: 2015-03-31
date_from : 2013-04-01
date_thru : 2015-03-31
So you should be able to say something like this:
select *
from foo t
where t.transaction_date between dateadd(year,-2, dateadd(day,1-day(#today),#today) )
and dateadd(day, -day(#today),#today)
If you have to deal with datetime values rather than date, its easier to not use between and say something like this:
declare #today date = current_timestamp -- get the current date without a time component
select *
from foo t
where t.transaction_date >= dateadd(year,-2, dateadd(day,1-day(#today),#today) )
and t.transaction_date < dateadd(year, 0, dateadd(day, -day(#today),#today)
[superfluous addition of 0 years added for clarity]
I have codes like this:
select CUS_Id, CUS_Name, CUS_JoinDate
from CUSTOMER
where CUS_joinDate between '04-12-2013' and '06-12-2013'
How can I make it 'where' CUS_JoinDate will be declare as from Today Date(minus 1 month and today + 1 month)?
So every time I run the report it will depends on the current date and it will automatically minus and plus 30 days.
try,
WHERE CUS_joinDate BETWEEN DATEADD(mm,-1,GETDATE()) AND DATEADD(mm,1,GETDATE())
SQLFiddle Demo
You can use CURDATE() and DATEADD()
W3SCHOOLS SQL DATES
Try this one:
select CUS_Id, CUS_Name, CUS_JoinDate
from CUSTOMER
where CUS_joinDate BETWEEN DATEADD(DAY,-1,GETDATE()) AND DATEADD(DAY,1,GETDATE())
However, if you need to add months/years to date, you need to use DATEADD() function.
It can be used as:
SELECT GETDATE(), 'Today'
UNION ALL
SELECT DATEADD(DAY, 10, GETDATE()), '10 Days Later'
UNION ALL
SELECT DATEADD(DAY, –10, GETDATE()), '10 Days Earlier'
UNION ALL
SELECT DATEADD(MONTH, 1, GETDATE()), 'Next Month'
UNION ALL
SELECT DATEADD(MONTH, –1, GETDATE()), 'Previous Month'
UNION ALL
SELECT DATEADD(YEAR, 1, GETDATE()), 'Next Year'
UNION ALL
SELECT DATEADD(YEAR, –1, GETDATE()), 'Previous Year'
Result Set:
2011-05-20 21:11:42.390 Today
2011-05-30 21:11:42.390 10 Days Later
2011-05-10 21:11:42.390 10 Days Earlier
2011-06-20 21:11:42.390 Next Month
2011-04-20 21:11:42.390 Previous Month
2012-05-20 21:11:42.390 Next Year
2010-05-20 21:11:42.390 Previous Year