Two columns with dates (one any day of week, another one WEEK ENDING DATE (SATURDAY) BASED ON 1st column) - sql

I have such a situation.
I need to have 2 columns 1) Is just pull data from a table (just as it is) r.[RCLDTE] (Day of week)
and 2 column) I need to basically look at the first column and make it Saturday of that week.
SELECT r.[RCLDTE] AS 'Day of Week'
,r.[RCLDTE] AS 'Week Ending Day (Saturday)'
Before what I was doing at similar projects I just used this code and added to WHERE statement.
WHERE CONVERT(DATE, CONVERT(CHAR(8), r.[RCLDTE] )) = cast(DATEADD(dd, DATEPART(DW,GETDATE())*-1, GETDATE()) as date)
This code was changing the dates column to Saturday.
However, here I have a different situation. I need 2 columns 1) as it is and 2) where dates will be Saturdays of the week from r.[RCLDTE] column , as a result from the way how I understand I cannot use WHERE statement because it will affect both columns.
Does someone know how I can leave 1st column as it is and 2nd a column of Saturday.
Please let me know.
Thanks.

To avoid issues when someone changes either DATEFIRST or LANGUAGE settings, you can use this. Also, given that you are storing dates in a numeric column for some reason (you really should provide feedback to whoever owns the system so they can fix it), we have to first try to convert those values to a date (they may not all be valid, which is one of the problems with using the wrong data type):
;WITH t AS
(
SELECT *, ProperDate = CASE WHEN ISDATE(CONVERT(char(8), RCLDTE)) = 1
THEN CONVERT(date, CONVERT(char(8), RCLDTE)) END
FROM dbo.tablename
)
SELECT [Language] = ##language, [Datefirst] = ##datefirst,
RCLDTE = CASE WHEN ProperDate IS NULL THEN RCLDTE END,
[Day of Week] = ProperDate,
[Saturday] = DATEADD
(
DAY,
6 - ((DATEPART(WEEKDAY, ProperDate) + ##DATEFIRST - 1) % 7),
ProperDate
)
FROM t;
Updated db<>fiddle that also demonstrates the handling of garbage data and a version of SQL Server so old that TRY_CONVERT() didn't exist yet (at least 12 years ago).

here is one way :
select
r.RCLDTE AS 'Day of Week'
, dateadd(day, 7 - datepart(weekday, r.RCLDTE) , r.RCLDTE)
from tablename r
db<>fiddle here

Related

SQL Changing Date by one workday and filter for it

I'm running the following query
SELECT a.DAT
FROM a
and getting a column of datetimes. I would like to change this column or alternatively add a column, that adds a workday to the corresponding datetime and I want to be able to filter for the date at the same time
My approach for changing the workday is like this CASE WHEN DATENAME(dw, date) = 'Friday' THEN DATEADD(dw, 3, date), but I don't know how to fit that in. Here I'm adding 3 days to Friday because it should skip to Monday the next workday, in the other cases I would add only 1 day, for Monday to Thursday.
Maybe there is a better way?
In this image I tried to show how the result of an examplatory query should
look like. I have all dates available but I want to filter for the 14th, which should show me the 11 dates, because of the added workday. Since June 11 is Friday
I think my Main problem is I don't know how make the extra column depending on the given datetime, it should add 3 on Fridays and 1 on every other day (Saturday and Sunday don't exist in the base data)
Thanks for your responses.
I have a solution now. If it can be easier, let me know, if you like. Anyway, thanks for your help everyone
Solution:
DECLARE #Date DATETIME
Set #Date = '14/06/2021'
SELECT
a.DAT,
(CASE WHEN DATENAME(dw, a.DAT) = 'Friday' THEN DATEADD(DAY, 3, a.DAT) ELSE DATEADD(DAY, 1, a.DAT) END) as RealDate
FROM a
WHERE (CASE WHEN DATENAME(dw, #Date) = 'Monday' THEN DATEADD(DAY, -3, #Date) ELSE DATEADD(DAY, -1, #Date) END) = a.DAT
You seem to be describing a case expression:
SELECT (CASE WHEN DATENAME(weekday, date) = 'Friday'
THEN DATEADD(DAY, 3, date)
ELSE DATEADD(DAY, 1, date)
END) as next_date
Welcome to S/O. If your table already has a datetime column, that is probably best. Dont try to break things down such as a date column, a time column, and some workday column. There are plenty of functions that allow you to extract parts as needed. However, your post tags only show SQL instead of a specific database such as sql-server, mysql, oracle, etc. but appears SQL-Server via DateAdd() function.
With date functions you could do things like filtering based on the "Day" of the given date/time column NOT being a Sat or Sun. Or, filtering on a single month by a >= first day of the month but less than first day of following month. This way you dont have to worry about time factors. This type of query would allow inclusion of working up to 11:59:59pm before following day.
If you edit your question with any additional clarifications on why adding 3 days per your example may help offer additional resolution. Try not to just put things that could be long in comments. Then just comment back on my post and I'll try to follow-up (in addition to others that may follow this post).

Data Preparation End OF Every Month - Moving Over 12 Months

I have data prep procedure in SQL. I want to have data preparation at the end of every month
Say I want the procedure run on last day of month e.g. on 31 January 2020 it should prep data from 1 January to 31 January.
So it's kind of moving window over all months of the year. Because I need data for evaluation at the end of each month.
I tried this, however, this does not give automation. Its sort of manual running end of every month
select '2020-10-01' as beginDate_AnalysisWindow
, '2020 -01-31' as endDate_AnalysisWindow
into #AnalysisWindow --create temporary table #AnalysisWindow
I also tried the following, however, I’m not sure if it does for the whole month or just one day?
SELECT START_OF_MONTH_DATE AS beginDate_AnalysisWindow
,END_OF_MONTH_DATE AS endDate_AnalysisWindow
INTO #AnalysisWindow
FROM [dbo].[Date] WITH (NOLOCK)
WHERE DATE = DATEADD(dd, - 1, CAST(GETDATE() AS DATE))
Could someone pls help me/give me some suggestions.
Thanks in advance
If you want the last day of the current month, use eomonth():
WHERE DATE = CONVERT(date, EOMONTH(GETDATE()))
Note: This assumes that the date column has no time component. If that is the case:
WHERE CONVERT(date, DATE) = CONVERT(date, EOMONTH(GETDATE()))
SQL Server will still use an index (if available) even for this type of conversion.
EDIT:
To get the current months data, one method is:
WHERE DATE <= CONVERT(date, EOMONTH(GETDATE())) AND
DATE > CONVERT(date, EOMONTH(GETDATE(), -1))
The second argument to EOMONTH() is a months offset.
You can also try:
where getdate() <= EOMONTH(GETDATE()) AND
getdate() > DATEADD(DAY, 1, EOMONTH(GETDATE(), -1))
Instead of getdate(), you can use your date column.

SSRS. Workday Function

I'm trying to convert the below Excel formula into SSRS but having looked around I cannot seem to find a solution. I can calculate the number of working days between two dates but what I'm trying to do is add on a number of working days to a date. Essentially I don't have the 2nd date.
I guess it would be something along the lines of the DATEADD function?
=WORKDAY($A1,B$1)
Hope someone can help
Many thanks
Here is a tsql solution to add X Business Days to a date.
declare #calendar as table (theDate date, dayOfWeek varchar (10));
declare #startDate as date = '20170704';
declare #businessDaysToAdd as integer = 10;
insert into #calendar
select theDate
, datename(dw, theDate) dow
from
dbo.dateTable('20170701', '20170720') ;
with temp as (
select theDate
, dayOfWeek
, rank() over (order by theDate) theRank
from #calendar
where theDate > #startDate
and dayOfWeek not in ('Saturday', 'Sunday')
)
select * from temp
where theRank = #businessDaysToAdd;
Notes
dbo.DateTable is a table valued function that just happens to exist in the database I was using. In real life, you might have an actual calendar table of some sort.
This example does not include holidays.
This is only the start of the answer to the posted question. It only solves the problem of Essentially I don't have the 2nd date.
Type this into the expression for the textbox. (From SSRS 2008 Datediff for Working Days)
=(DateDiff(DateInterval.day,Parameters!STARTDATE.Value,Parameters!ENDDATE.Value)+1)
-(DateDiff(DateInterval.WeekOfYear,Parameters!STARTDATE.Value,Parameters!ENDDATE.Value)*2)
-(iif(Weekday(Parameters!STARTDATE.Value) = 7,1,0)
-(iif(Weekday(Parameters!ENDDATE.Value) = 6,1,0))-1)
Ok after much perseverance I managed to get what I wanted in both TSQL and SSRS. My objective was to measure Agent productivity so I didn’t want to count the weekend and this would be unfair. If a date fell on a weekend then I wanted it to jump to a Monday. Likewise if adding number of days onto a date went over a weekend in the future then I needed the incremented date to reflect this. For the end user (In SSRS) I wanted a leading edge (Like an Upside down triangle) so that if the date + number working days was in the future then set to NULL, showing a zero would look like no productivity which is incorrect.
First TSQL - My base query started with the following SO thread but after trying many of the options I was finding when the date fell on a Saturday or Sunday the solution did not work for me (I was unable to create functions due to permissions). However tweaking the below got me there and I dealt with Sunday specifically
Add business days to date in SQL without loops
SELECT
,DATEADD(WEEKDAY, (/*Your Working Days*//5)*7+(/*Your Working Days*/ % 5) +
(CASE WHEN DATEPART(WEEKDAY,/*Your Date*/) <>7 AND DATEPART(WEEKDAY,/*Your Date*/) + (/*Your Working Days*/ % 5) >5 THEN 2
WHEN DATEPART(WEEKDAY,/*Your Date*/) = 7 AND DATEPART(WEEKDAY,/*Your Date*/) + (/*Your Working Days*/ % 5) >5 THEN 1 ELSE 0 END), /*Your Date*/) AS [IncrementedDate]
FROM /*YourTable*/
Then for SSRS - The 2 key points here is that TSQL will divide as an integer if the source number is an integer so this needs to be handled in SSRS and secondly you need to set the first week day to Monday as part of the expression.
I put this expression into a Matrix with Date Created being my Row Group and Contact Working Days being my Column Group.
=DATEADD("W",(INT(ReportItems!ContactWorkingDays.Value/5))*7+(ReportItems!ContactWorkingDays.Value MOD 5) + IIF(DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) <> 7 AND (DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) + (ReportItems!ContactWorkingDays.Value MOD 5) >5),2,IIF(DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) = 7 AND (DATEPART("W",ReportItems!DateCreated.Value,FirstDayOfWeek.Monday) + (ReportItems!ContactWorkingDays.Value MOD 5) >5),1,0)),ReportItems!DateCreated.Value)
This does not include holidays - I'm not too bothered at this stage and that is for a rainy day! :)

Capture the first of the current month to current day date range in where clause

I am selecting fields like client id, name, and service date. I am trying to write in my where clause, that every day I run my query it will capture a date range of the first of the current month to the current day.
One method would be to compare the month and the year:
where year(col) = year(getdate()) and
month(col) = month(getdate()) and
day(col) <= day(getdate()) -- this is optional, if there is no future data
Another method would be to compare to the beginning of the month. I would approach this as:
where col >= cast(dateadd(day, 1 - day(getdate), getdate()) as date)
(This assumes there is no future data in the table.)
or, better yet:
where col >= datefromparts(year(getdate()), month(getdate()), 1)
Select *
From YourTable
where SomeDateField bewteen cast(DateAdd(DD,-Day(GetDate())+1,GetDate()) as Date) and cast(getDate() as Date)
and ...
Edit: I used the BETWEEN to trap possible future date/scheduled events

Get date for nth day of week in nth week of month

I have a column with values like '3rd-Wednesday', '2nd-Tuesday', 'Every-Thursday'.
I'd like to create a column that reads those strings, and determines if that date has already come this month, and if it has, then return that date of next month. If it has not passed yet for this month, then it would return the date for this month.
Expected results (on 4/22/16) from the above would be: '05-18-2016', '05-10-2016', '04-28-2016'.
I'd prefer to do it mathematically and avoid creating a calendar table if possible.
Thanks.
Partial answer, which is by no means bug free.
This doesn't cater for 'Every-' entries, but hopefully will give you some inspiration. I'm sure there are plenty of test cases this will fail on, and you might be better off writing a stored proc.
I did try to do this by calculating the day name and day number of the first day of the month, then calculating the next wanted day and applying an offset, but it got messy. I know you said no date table but the CTE simplifies things.
How it works
A CTE creates a calendar for the current month of date and dayname. Some rather suspect parsing code pulls the day name from the test data and joins to the CTE. The where clause filters to dates greater than the Nth occurrence, and the select adds 4 weeks if the date has passed. Or at least that's the theory :)
I'm using DATEFROMPARTS to simplify the code, which is a SQL 2012 function - there are alternatives on SO for 2008.
SELECT * INTO #TEST FROM (VALUES ('3rd-Wednesday'), ('2nd-Tuesday'), ('4th-Monday')) A(Value)
SET DATEFIRST 1
;WITH DAYS AS (
SELECT
CAST(DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE()),N.Number) AS DATE) Date,
DATENAME(WEEKDAY, DATEADD(MONTH,DATEDIFF(MONTH,0,GETDATE()),N.Number)) DayName
FROM master..spt_values N WHERE N.type = 'P' AND N.number BETWEEN 0 AND 31
)
SELECT
T.Value,
CASE WHEN MIN(D.Date) < GETDATE() THEN DATEADD(WEEK, 4, MIN(D.DATE)) ELSE MIN(D.DATE) END Date
FROM #TEST T
JOIN DAYS D ON REVERSE(SUBSTRING(REVERSE(T.VALUE), 1, CHARINDEX('-', REVERSE(T.VALUE)) -1)) = D.DayName
WHERE D.Date >=
DATEFROMPARTS(
YEAR(GETDATE()),
MONTH(GETDATE()),
1+ 7*(CAST(SUBSTRING(T.Value, 1,1) AS INT) -1)
)
GROUP BY T.Value
Value Date
------------- ----------
2nd-Tuesday 2016-05-10
3rd-Wednesday 2016-05-18
4th-Monday 2016-04-25