SQL replace date values if date is Saturday or Sunday - sql

(Sorry, I couldn't think of a better title)
I have created the following select statement (SQL Server) to work as a view.
SELECT DISTINCT
dbo.ECB.Currency + '-' +
CAST(dbo.ECB.Date AS varchar(30)) AS ComboDate,
dbo.ECB.Rate AS ECBrate
FROM
dbo.ECB
INNER JOIN
dbo.MyTable ON dbo.ECB.Date = dbo.MyTable.CutoffDate
AND dbo.ECB.Currency = dbo.MyTable.MyCurrency
My problem:
What I've noticed is that I have Saturday and Sunday dates in my CutoffDate column but not in the ECB date column - meaning I have no rates for those days.
Since I use the CutoffDate in Excel calculations I would like the view to "replace" the date values for Saturday and Sunday with Friday.
I found this working snippet and modified it to my needs.
SELECT
DISTINCT
CASE WHEN DATEPART(weekday, dbo.CutoffDate) IN (6, 7)
THEN DATEADD(d, -((DATEPART(weekday, dbo.CutoffDate) + 1 + ##DATEFIRST) % 7), dbo.CutoffDate)
ELSE dbo.CutoffDate
END
FROM
MyTable
Now I need to find a way to combine both structures and this is where I'm hoping that you can help me out with.
I wanted to add the second select statement to my view but failed in doing so.
thank you.

If you move your case statement into the join, it should work.
Change
dbo.MyTable ON dbo.ECB.Date = dbo.MyTable.CutoffDate
To
dbo.Mytable ON dbo.ECB.Date = case when datepart(weekday, dbo.CutoffDate) IN (6,7)
then dateadd(d, -((datepart(weekday, dbo.CutoffDate) + 1 + ##DATEFIRST) % 7), dbo.CutoffDate)
else dbo.CutoffDate
end
Hope this helps.

Related

SQL Find/Ignore invalid date

I am using SQL Server.
From each row, I take day and month values from the fields c.daybirth,c.monthbirth
and the year from getdate(), and I want to have a field that shows if this date is valid or not (invalid example: 31 February)
I have created this solution:
case day(dateadd(month,c.monthbirth-1,dateadd(day,c.daybirth-1,DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))) when c.daybirth then 1 else 0 end
which works, but I find it hard to read. Is there a smarter alternative?
In SQL Server 2012+, you can do:
where try_convert(date,
datefromparts(year(getdate()), c.monthbirth, c.daybirth)
) is not null
EDIT:
Amusing. This is better:
where try_convert(date,
cast(year(getdate()) * 10000 + c.monthbirth * 100 + c.daybirth as varchar(255))
) is not null

How to update date , but date/day should not be sat or sunday

I have a Execute SQL task in SSIS, which updates date in Database to today's date+3. But if suppose today is Thursday say(18/6/2015) and jobs executes then according to update query date in Database will be update to (21/6/2015) out of which 20th and 21st are Sat and Sunday. Instead i would want the date to be updated to 23/6/2015 i.e Tuesday( excluding Sat and Sunday). Please help!
I've made the following SELECT statement which may help you.
Using the DATEPART function you can discover which day of the week a sum of days will be.
DATEPART returns a number representing the day of the week of the date passed as parameter to the function, considering 1 is Sunday and 7 is Saturday.
select CASE
WHEN DATEPART(DW, GETDATE() + 4) = 7 THEN (SELECT GETDATE() + 6)
WHEN DATEPART(DW, GETDATE() + 5) = 1 THEN (SELECT GETDATE() + 5)
END As date
Using this example in an update statement:
UPDATE <your table>
SET dateofanything = (CASE
WHEN DATEPART(DW, GETDATE() + 3) = 7 THEN (SELECT GETDATE() + 5)
WHEN DATEPART(DW, GETDATE() + 3) = 1 THEN (SELECT GETDATE() + 4)
END As date)

default date value of every Friday in SQL Server?

In SQL Server 2008 i want to set a default date value of every Friday to show up in the column when i insert a new record?
ALTER TABLE myTable ADD CONSTRAINT_NAME DEFAULT GETDATE() FOR myColumn
Whats the best way to show every Friday?
I want the default value to be based on the now date then knowing that the next available date is 05-07/2013
I have the following:
dateadd(d, -((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate())
But when passing todays date, it gave me: 2013-06-28 which is actually LAST Friday!, it should be the up and coming Friday!
SELECT DATEADD(day,-3, DATEADD(week, DATEDIFF(week, 0, current_timestamp)+1, 0)) AS LastFridayDateOfWeek
Gets the last date of current week (sunday) then subtracts 3 from that to get Friday.
Replace current_timestamp if you need a different dates friday.
EDIT:
I thought about this a bit, and if the above (Friday THIS WEEK, so for Saturday it gives the previous date) does not work, you could easily use a reference date set like so:
DATEADD(DAY,7 + DATEDIFF(day,'20100109',#checkDateTime)/7*7,'20100108') as FridayRefDate
Same thing but with no hard coded Friday/Saturday in it:
DATEADD(DAY,7 + DATEDIFF(day,DATEADD(wk, DATEDIFF(wk,0,#checkDateTime),5),#checkDateTime)/7*7,DATEADD(wk, DATEDIFF(wk,0,#checkDateTime), 4))
So for 20100109 is a Friday.
SET #checkDateTime = '2012-01-14 3:34:00.000'
SELECT DATEADD(DAY,7 + DATEDIFF(day,'20100109',#checkDateTime)/7*7,'20100108') as FridayRefDate
it returns "2012/1/20"
But for SET #checkDateTime = '2012-01-13 3:34:00.000' it returns "2012/1/13"
If your current query gives you last Friday, the easiest thing to do is simply to add 7 to it:
select dateadd(d, 7-((datepart(weekday, getdate()) + 1 + ##DATEFIRST) % 7), getdate())
------------------^
SELECT CONVERT(DATE, ( CASE WHEN DATEPART(dw, GETDATE()) - 6 <= 0
THEN DATEADD(dd,
( DATEPART(dw, GETDATE()) - 6 ) * -1,
GETDATE())
ELSE DATEADD(dd, ( DATEPART(dw, GETDATE()) ) - 1,
GETDATE())
END )) AS NearestFriday
Just add 7 to the formula
SELECT DATEADD(dd,CAST(5-GETDATE() AS int)%7,GETDATE()+7)
To verify the formula:
WITH test AS (
SELECT GETDATE() AS d UNION ALL
SELECT DATEADD(dd,1,d)
FROM test WHERE d < GETDATE() + 30
)
SELECT
d AS [input],
DATEADD(dd,CAST(5-d AS int)%7,d+7) AS [output]
FROM test
To tweak the the formula, adjust the 5- and the +7

(sql server 2005) How to determine the WEEK number starting from GETDATE() [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting week number off a date in MS SQL Server 2005?
Please suppose (i am in Italy) that all the weeks start with Monday and end with Sunday.
I would like to write a scalar valued function that determines the number of the week with reference to GETDATE()
Thank you in advance for your kind cooperation.
PLEASE PAY ATTENTION TO THIS: The SELECT has to be INDIPENDENT from the SET DATEFIRST command!!
Can you use the two liner?
SET DATEFIRST 1;
SELECT DATEPART( WEEK , GETDATE())
for today
SELECT DATEPART( WEEK , GETDATE())
returns 30 whereas
SET DATEFIRST 1;
SELECT DATEPART( WEEK , GETDATE())
returns 31
Edit Untested but based on This Question you can get the equivalent of the SQL Server 2008 datepart(iso_week, getdate()) (which i believe is what you want) with the following select statement
SELECT ISOWeek = (DATEPART(DY, Th) - 1) / 7 + 1
FROM (SELECT Th = DATEADD(D, 3 - (DATEPART(DW, getdate()) + ##DATEFIRST - 2) % 7, getdate())) s
Here's a little snippet that should do what you need.
DECLARE #firstOfYear DATETIME
SET #firstOfYear = STR(Year(GETDATE()), 4)+'-01-01 00:00:00'
SELECT DATEDIFF(ww, #firstOfYear - ((DATEPART(dw, #firstOfYear) + 5) % 7), GETDATE())
Keep in mind that if you want to set the week start to on a different day, just change the +5 to the value based on 7 - dw. This is for MSSQL.
This works by getting the first day of the year and finding the day of the starting week on or before that day. Then we get the number of weeks between whatever date was passed in and that "first" week start. If you want to allow any date to be passed in, just replace all GETDATE calls with your parameter and you should be good to go. If you need a single select statement:
SELECT
DATEDIFF(ww, day1 - ((DATEPART(dw, day1) +5) % 7), GETDATE())
FROM
(SELECT CAST(STR(Year(GETDATE()), 4)+'-01-01 00:00:00' AS DATETIME) day1) d
select datepart(week,getdate())
more at http://msdn.microsoft.com/en-us/library/aa258265(v=sql.80).aspx
declare #oldDF int
set #oldDF = ##DATEFIRST
set DATEFIRST 1
select DATEPART(WEEK, GETDATE())
set DATEFIRST #oldDF

Calculating in SQL the first working day of a given month

I have to calculate all the invoices which have been paid in the first 'N' days of a month. I have two tables
. INVOICE: it has the invoice information. The only field which does matter is called 'datePayment'
. HOLYDAYS: It is a one column table. Entries at this table are of the form "2009-01-01",
2009-05-01" and so on.
I should consider also Saturdays and Sundays
(this might be not a problem because I could insert those days at the Hollidays table in order to consider them as hollidays if neccesary)
The problem is to calculate which is the 'payment limit'.
select count(*) from invoice
where datePayment < PAYMENTLIMIT
My question is how to calculate this PAYMENTLIMIT. Where PAYMENTLIMIT is 'the fifth working day of every month'.
The query should be run under Mysql and Oracle therefore standard SQL should be used.
Any hint?
EDIT
In order to be consistent with the title of the question the pseudo-query should the read as follows:
select count(*) from invoice
where datePayment < FIRST_WORKING_DAY + N
then the question can be reduced to calculate the FIRST_WORKING_DAY of every month.
You could look for the first date in a month, where the date is not in the holiday table and the date is not a weekend:
select min(datePayment), datepart(mm, datePayment)
from invoices
where datepart(dw, datePayment) not in (1,7) --day of week
and not exists (select holiday from holidays where holiday = datePayment)
group by datepart(mm, datePayment) --monthnr
Something like this might work:
create function dbo.GetFirstWorkdayOfMonth(#Year INT, #Month INT)
returns DATETIME
as begin
declare #firstOfMonth VARCHAR(20)
SET #firstOfMonth = CAST(#Year AS VARCHAR(4)) + '-' + CAST(#Month AS VARCHAR) + '-01'
declare #currDate DATETIME
set #currDate = CAST(#firstOfMonth as DATETIME)
declare #weekday INT
set #weekday = DATEPART(weekday, #currdate)
-- 7 = saturday, 1 = sunday
while #weekday = 1 OR #weekday = 7
begin
set #currDate = DATEADD(DAY, 1, #currDate)
set #weekday = DATEPART(weekday, #currdate)
end
return #currdate
end
I'm not 100% sure about whether the "weekday" numbers are fixed or might depend on your locale on your SQL Server. Check it out!
Marc
Rather than a Holidays table of days to exclude, we use the calendar table approach: one row for every day the application will ever need (thirty years spans a modest 11K rows). So not only does it have an is_weekday column, it has other things relevant to the enterprise e.g. julianized_date. This way, every possible date would have a ready-prepared value for first_working_day_this_month and finding it involves a simple lookup (which SQL products tend to be optimized for!) rather than 'calculating' it each time on the fly.
We have dates table in our application (filled with all dates and date parts for some tens of years), what allows various "missing" date manipulations, like (in pseudo-sql):
select min(ourdates.datevalue)
from ourdates
where ourdates.year=<given year> and ourdates.month=<given month>
and ourdates.isworkday
and not exists (
select * from holidays
where holidays.datevalue=ourdates.datevalue
)
Ok, at a first stab, you could put the following code into a UDF and pass in the Year and Month as variables. It can then return TestDate which is the first working day of the month.
DECLARE #Month INT
DECLARE #Year INT
SELECT #Month = 5
SELECT #Year = 2009
DECLARE #FirstDate DATETIME
SELECT #FirstDate = CONVERT(varchar(4), #Year) + '-' + CONVERT(varchar(2), #Month) + '-' + '01 00:00:00.000'
DROP TABLE #HOLIDAYS
CREATE TABLE #HOLIDAYS (HOLIDAY DateTime)
INSERT INTO #HOLIDAYS VALUES('2009-01-01 00:00:00.000')
INSERT INTO #HOLIDAYS VALUES('2009-05-01 00:00:00.000')
DECLARE #DateFound BIT
SELECT #DateFound = 0
WHILE(#DateFound = 0)
BEGIN
IF(
DATEPART(dw, #FirstDate) = 1
OR
DATEPART(dw, #FirstDate) = 1
OR
EXISTS(SELECT * FROM #HOLIDAYS WHERE HOLIDAY = #FirstDate)
)
BEGIN
SET #FirstDate = DATEADD(dd, 1, #FirstDate)
END
ELSE
BEGIN
SET #DateFound = 1
END
END
SELECT #FirstDate
The things I don`t like with this solution though are, if your holidays table contains all days of the month there will be an infinite loop. (You could check the loop is still looking at the right month) It relies upon the dates being equal, eg all at time 00:00:00. Finally, the way I calculate the 1st of the month past in using string concatenation was a short cut. There are much better ways of finding the actual first day of the month.
Gets the first N working days of each month of year 2009:
select * from invoices as x
where
datePayment between '2009-01-01' and '2009-12-31'
and exists
(
select
1
from invoices
where
-- exclude holidays and sunday saturday...
(
datepart(dw, datePayment) not in (1,7) -- day of week
/*
-- Postgresql and Oracle have programmer-friendly IN clause
and
(datepart(yyyy,datePayment), datepart(mm,datePayment))
not in (select hyear, hday from holidays)
*/
-- this is the MSSQL equivalent of programmer-friendly IN
and
not exists
(
select * from holidays
where
hyear = datepart(yyyy,datePayment)
and hmonth = datepart(mm, datePayment)
)
)
-- ...exclude holidays and sunday saturday
-- get the month of x datePayment
and
(datepart(yyyy, datePayment) = datepart(yyyy, x.datePayment)
and datepart(mm, datePayment) = datepart(mm, x.datePayment))
group by
datepart(yyyy, datePayment), datepart(mm, datePayment)
having
x.datePayment < MIN(datePayment) + #N -- up to N working days
)
Returns the first Monday of the current month
SELECT DATEADD(
WEEK,
DATEDIFF( --x weeks between 1900-01-01 (Monday) and inner result
WEEK,
0, --1900-01-01
DATEADD( --inner result
DAY,
6 - DATEPART(DAY, GETDATE()),
GETDATE()
)
),
0 --1900-01-01 (Monday)
)
SELECT DATEADD(day, DATEDIFF (day, 0, DATEADD (month, DATEDIFF (month, 0, GETDATE()), 0) -1)/7*7 + 7, 0);
select if(weekday('yyyy-mm-01') < 5,'yyyy-mm-01',if(weekday('yyyy-mm-02') < 5,'yyyy-mm-02','yyyy-mm-03'))
Saturdays and Sundays are 5, 6 so you only need two checks to get the first working day