Hello I've converted a spreadsheet into a SSRS report which is run on the 20th of month and I need to pass the 20th of the current month as a default value (start date) either through a custom expression or dataset. If the 20th falls on a Saturday, default to friday 19th. If the 20th falls on Sunday default to Friday 18th. How do I do this and what is the best way of doing it?
How about this:
DECLARE #daytwenty date;
SET #daytwenty = DATEADD(mm, DATEDIFF(mm, 0, getdate()) ,19) --Get Twentieth Day of current month
SELECT
CASE DATEPART(DW,#daytwenty)
WHEN 1 THEN DATEADD(dd, -2, #daytwenty) --When the twentieth day is a Sunday, take two days off
WHEN 7 THEN DATEADD(dd, -1, #daytwenty) --When the twentieth day is a Saturday, take one day off
ELSE #daytwenty --Else the twentieth day is a weekday already
END
You should use Datetime for 2008 version. By writing
DECLARE #LatestDate date;
in previous version of Sql Server gives compilation error.
Column, parameter, or variable #1: Cannot find data type date.
So below is the code Sql server 2008
DECLARE #LatestDate datetime;
SET #LatestDate = DATEADD(mm, DATEDIFF(mm, 0, getdate()) ,19) --Get Twentieth Day of current month
SELECT
CASE DATEPART(DW,#LatestDate)
WHEN 1 THEN DATEADD(dd, -2, #LatestDate) --When the twentieth day is a Sunday, take two days off
WHEN 7 THEN DATEADD(dd, -1, #LatestDate) --When the twentieth day is a Saturday, take one day off
ELSE #LatestDate --Else the twentieth day is a weekday already
END
I hope this is what u want,
select case datename(dw, getdate())
when 'Monday' then 'Friday'
when 'Tuesday' then 'Monday'
when 'Wednesday' then 'Tuesday'
when 'Thursday' then 'Wednesday'
when 'Friday' then 'Thursday'
when 'Saturday' then 'Friday'
when 'Sunday' then 'Friday'
end
Related
I would like to pull data into my query for JUST the previous day. When I run the query on Monday I would like to have data for Saturday and Sunday as well.
The below part of the query works fine but it does not include Sat and Sun when ran on a Monday. Can anyone give me an idea of what to add?
where ([ImportDate] = DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END,
DATEDIFF(DAY, 0, GETDATE())))
You were close. But you want to make it a range of dates that would include the previous days you want up to the current date, by using >= < or a BETWEEN.
where [ImportDate] >= DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE()) WHEN 'Sunday' THEN -2 WHEN 'Monday' THEN -3 ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
and [ImportDate] < CONVERT(DATE,GETDATE())
I have a stored procedure that produces a report each night. This SP references a view that takes a snapshot of data from 2 weeks ago (Sunday to Saturday).
I need to get the dates of the Saturday and Sunday from two weeks ago (so for today that would be 23/24 of December.
I have searched through many solutions but I am unable to find a decent response to this - any one able to help with an answer as well as explaining a little bit of the reason for doing it that way (it seems like there are a thousand ways to do it).
Thanks
Here is the answer in case any one needs it in future.
SELECT DATEADD(wk, -2, DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))
Try this (for Saturday) is the same for Sunday:
DECLARE #today datetime
SET #today = GETDATE()
SELECT
CASE
WHEN DATENAME(weekday, #today) = 'Monday' THEN DATEADD(day, -15, #today)
WHEN DATENAME(weekday, #today) = 'Tuesday' THEN DATEADD(day, -16, #today)
WHEN DATENAME(weekday, #today) = 'Wednesday' THEN DATEADD(day, -17, #today)
WHEN DATENAME(weekday, #today) = 'Thursday' THEN DATEADD(day, -18, #today)
WHEN DATENAME(weekday, #today) = 'Friday' THEN DATEADD(day, -19, #today)
WHEN DATENAME(weekday, #today) = 'Saturday' THEN DATEADD(day, -13, #today)
WHEN DATENAME(weekday, #today) = 'Sunday' THEN DATEADD(day, -14, #today)
END
DATENAME with weekday parameter returns the name of the day, so if you are on Monday you must subtract 15 days to reach Saturday and so on.
Pay attention: If you have another language set you can change it for your query using:
SET LANGUAGE us_english
You can see SqlFiddle
Since the day of week value can differ on different machines you either need to set it using the set datefirst 1 command as suggeste in Podiluska's answer,
or you can do it by first determining the actual value for sunday and add that to the days you are subtracting.
To determine the actual value for sunday simply ask the value for a know sunday, like 2018-01-07 for example
Below example should return 2017-12-23 / 2017-12-24
It will also return this if you are running this on friday, or thursday, or whatever day...
-- this will contain are test date
declare #date date = getdate() - 2
-- determine the number for sunday
declare #Sunday int = (select datepart(dw, '20180107'))
select convert(date,dateadd(d, -15 - datepart(dw, #date) + (datepart(dw, #date) - #Sunday), getdate())),
convert(date,dateadd(d, -14 - datepart(dw, #date) + (datepart(dw, #date) - #Sunday), getdate()))
That depends on how you define when your week starts, but the basic principle is to find the start of this week, and take away 14 days.
eg:
set datefirst 1
select convert(date,dateadd(d, -15-datepart(dw, getdate()), getdate())),
convert(date,dateadd(d, -14-datepart(dw, getdate()), getdate()))
Sorry, I'll work on a general form for these; this is the quick and dirty.
I like the NEXT_DAY function. Simple, and obvious as to what it does.
declare
vFromDate date := trunc( sysdate ) - 9 ; -- '27 Feb 2019'
vSatDate date ;
vSunDate date ;
begin
-- test a range of dates
while vFromDate <= sysdate -- '3 Mar 2019'
loop
select NEXT_DAY ( TRUNC ( vFromDate) - 21, 'SAT') -- 7: general form for these?
-- keep or discard the " - 1" depending on if the 2 wk Sunday is the desired Sunday
, NEXT_DAY ( TRUNC ( vFromDate) - 20 - 1, 'SUN') -- 1:
into vSatDate, vSunDate
from dual ;
dbms_output.put_line( to_char( vFromDate, 'dd Mon": "' )
|| to_char( vSatDate, 'dd Mon' )
|| to_char( vSunDate, '", "dd Mon' )
);
vFromDate := vFromDate + 1 ;
end loop ;
dbms_output.put_line( rpad('*', 21, '*' ) );
end ;
I am trying to make this a trigger, but so fat this is all I've got:
CREATE TRIGGER trg_SetDateToNextBusinessDay
ON dbo.Orders
AFTER INSERT
AS
UPDATE dbo.Orders
SET OrderDateTime = {next day that is Monday-Friday, 8:00 am}
WHERE OrderDateTime {is after 4:00} OR OrderDateTime {is on a saturday or sunday}
What is the easiest way to do this?
Try this:
CREATE TRIGGER trg_SetDateToNextBusinessDay
ON dbo.Orders
AFTER INSERT
AS
UPDATE dbo.Orders
SET OrderDateTime =
(CASE DATENAME(DW, OrderDateTime)
WHEN 'Friday' THEN DATEADD(DAY, DATEDIFF(DAY, -3, OrderDateTime), '08:00:00') -- if friday, add 3 days
WHEN 'Saturday' THEN DATEADD(DAY, DATEDIFF(DAY, -2, OrderDateTime), '08:00:00') -- if saturday add 2 days
ELSE DATEADD(DAY, DATEDIFF(DAY, -1, OrderDateTime), '08:00:00') -- on all other days just add one day
END) -- {next day that is Monday-Friday, 8:00 am}
WHERE DATEPART(HH, OrderDateTime) > 3 OR-- {is after 4:00} (this includes 4:00!)
DATENAME(DW, OrderDateTime) IN ('Saturday', 'Sunday') -- {is on a saturday or sunday}
To check if the date is a Saturday or Sunady I suggest datename.
You can check:
datename("dw", OrderDateTime) in ("Saturday", "Sunday").
You can use datepart to get the hour and check if it is after four.
datepart(hh, OrderDateTime) >= 4
For your set statement you can use a case:
case datename("dw", OrderDateTime)
when "Saturday"
then DATEADD(hh, 56,cast(OrderDateTime As Date))
when "Friday"
then DATEADD(hh, 80,cast(OrderDateTime As Date))
else DATEADD(hh, 32,cast(OrderDateTime As Date))
In all cases we are getting rid of the time. Then, if it is Saturday, add two days worth of hours to get us to Monday and add an additional eight hours to get us to eight am.
If it is Friday, add three days plus eight hours. Otherwise add a single day plus eight hours.
Please let me know how can I find if it is Sunday on given Date?
EDIT:
From answers another thing comes to my mind: How to find what is first day of week?
Use the "datename" function:
print datename(weekday, '11/29/2009')
or with a variable:
declare #date smalldatetime
set #date = '12/25/2008'
select datename(weekday, #date)
SELECT DATEPART(dw,theDateRow) AS dateOfWeek FROM someTable
dw stands for Day of Week
if dw = 0, it is Sunday.
A) Sunday Check
SELECT
CASE WHEN DATENAME(WEEKDAY, GETDATE()) != 'Sunday'
Then 'It is ' + CAST(DATENAME(WEEKDAY, GETDATE()) AS VARCHAR(10))
Else 'It is ' + CAST(DATENAME(WEEKDAY, GETDATE()) AS VARCHAR(10))
END 'Day is'
Output:
Day is
It is Saturday
B) Find first day of week
SELECT
DayName = DATENAME(WEEKDAY,
DATEADD(DD, 1 - DATEPART(DW, CONVERT(VARCHAR(10), GETDATE(), 111)),
CONVERT(VARCHAR(10), GETDATE(), 111))),
Date = DATEADD(DD,
1 - DATEPART(DW, CONVERT(VARCHAR(10), GETDATE(), 111)),
CONVERT(VARCHAR(10), GETDATE(), 111))
Output:
DayName Date
Sunday 2009-12-27 00:00:00.000
To find what is the first day of the week you use:
print ##datefirst
This will return a number from 1 to 7, where 1 = Monday, 2 = Tuesday... 7 = Sunday. You can change what is considered the first day of the week (on the SQL instance) by using:
set datefirst = 1
This will set the first day to Monday. By default SQL is set to 7 (Sunday) in US.
I have a table with a "Date" column, and I would like to do a query that does the following:
If the date is a Monday, Tuesday, Wednesday, or Thursday, the displayed date should be shifted up by 1 day, as in DATEADD(day, 1, [Date]) On the other hand, if it is a Friday, the displayed date should be incremented by 3 days (i.e. so it becomes the following Monday).
How do I do this in my SELECT statement? As in,
SELECT somewayofdoingthis([Date]) FROM myTable
(This is SQL Server 2000.)
Here is how I would do it. I do recommend a function like above if you will be using this in other places.
CASE
WHEN
DATEPART(dw, [Date]) IN (2,3,4,5)
THEN
DATEADD(d, 1, [Date])
WHEN
DATEPART(dw, [Date]) = 6
THEN
DATEADD(d, 3, [Date])
ELSE
[Date]
END AS [ConvertedDate]
CREATE FUNCTION dbo.GetNextWDay(#Day datetime)
RETURNS DATETIME
AS
BEGIN
DECLARE #ReturnDate DateTime
set #ReturnDate = dateadd(dd, 1, #Day)
if (select datename(#ReturnDate))) = 'Saturday'
set #ReturnDate = dateadd(dd, 2, #ReturnDate)
if (select datename(#ReturnDate) = 'Sunday'
set #ReturnDate = dateadd(dd, 1, #ReturnDate)
RETURN #ReturnDate
END
Try
select case when datepart(dw,[Date]) between 2 and 5 then DATEADD(dd, 1, [Date])
when datepart(dw,[Date]) = 6 then DATEADD(dd, 3, [Date]) else [Date] end as [Date]
I'm assuming that you also want Saturday and Sunday to shift forward to the following Monday. If that is not the case, take the 1 out of (1,2,3,4,5) and remove the last when clause.
case
--Sunday thru Thursday are shifted forward 1 day
when datepart(weekday, [Date]) in (1,2,3,4,5) then dateadd(day, 1, [Date])
--Friday is shifted forward to Monday
when datepart(weekday, [Date]) = 6 then dateadd(day, 3, [Date])
--Saturday is shifted forward to Monday
when datepart(weekday, [Date]) = 7 then dateadd(day, 2, [Date])
end
You can also do it in one line:
select dateadd(day, 1 + (datepart(weekday, [Date])/6) * (8-datepart(weekday, [Date])), [Date])
Sounds like a CASE expression. I don't know the proper data manipulations for SQL Server, but basically it would look like this:
CASE
WHEN [Date] is a Friday THEN DATEADD( day, 3, [Date] )
ELSE DATEADD( day, 1, [Date] )
END
If you wanted to check for weekend days you could add additional WHEN clauses before the ELSE.
you could use this:
select dayname,newdayname =
CASE dayname
WHEN 'Monday' THEN 'Tuesday'
WHEN 'Tuesday' THEN 'Wednesday'
WHEN 'Wednesday' THEN 'Thursday'
WHEN 'Thursday' THEN 'Friday'
WHEN 'Friday' THEN 'Monday'
WHEN 'Saturday' THEN 'Monday'
WHEN 'Sunday' THEN 'Monday'
END
FROM UDO_DAYS
results:
Monday Tuesday
Tuesday Wednesday
Wednesday Thursday
Thursday Friday
Friday Monday
Saturday Monday
Sunday Monday
table data:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
Look up the CASE statement and the DATEPART statement. You will want to use the dw argument with DATEPART to get back an integer that represents the day of week.
This is off the top of my head and can be clearly cleaned up but use it as a starting point:
select case when DATENAME(dw, [date]) = 'Monday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Tuesday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Wednesday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Thursday' then DATEADD(dw, 1, [Date])
when DATENAME(dw, [date]) = 'Friday' then DATEADD(dw, 3, [Date])
end as nextDay
...
How about taking a page from the Data Warehouse guys and make a table. In DW terms, this would be a date dimension. A standard date dimension would have things like various names for a date ("MON", "Monday", "August 22, 1998"), or indicators like end-of-month and start-of-month. However, you can also have columns that only make sense in your environment.
For instance, based on the question, yours might have a next-work-day column that would point to the key for the day in question. That way you can customize it further to take into account holidays or other non-working days.
The DW folks are adamant about using meaningless keys (that is, don't just use a truncated date as the key, use a generated key), but you can decide that for yourself.
The Date Dimension Toolkit has code to generate your own tables in various DBMS and it has CSV data for several years worth of dates.
you need to create a SQL Function that does this transformation for you.
This is mostly like Brian's except it didn't compile due to mismatched parens and I changed the IF to not have the select in it. It is important to note that we use DateNAME here rather than datePART because datePART is dependent on the value set by SET DATEFIRST, which sets the first day of the week.
CREATE FUNCTION dbo.GetNextWDay(#Day datetime)
RETURNS DATETIME
AS
BEGIN
DECLARE #ReturnDate DateTime
set #ReturnDate = dateadd(dd, 1, #Day)
if datename(dw, #ReturnDate) = 'Saturday'
set #ReturnDate = dateadd(dd, 2, #ReturnDate)
if datename(dw, #ReturnDate) = 'Sunday'
set #ReturnDate = dateadd(dd, 1, #ReturnDate)
RETURN #ReturnDate
END
create table #dates (dt datetime)
insert into #dates (dt) values ('1/1/2001')
insert into #dates (dt) values ('1/2/2001')
insert into #dates (dt) values ('1/3/2001')
insert into #dates (dt) values ('1/4/2001')
insert into #dates (dt) values ('1/5/2001')
select
dt, day(dt), dateadd(dd,1,dt)
from
#dates
where
day(dt) between 1 and 4
union all
select
dt, day(dt), dateadd(dd,3,dt)
from
#dates
where
day(dt) = 5
drop table #dates