How to find closest FRI? - sql

In SQL Server 2008, given a date, how would I get a date corresponding to FRI of that week?
so for example:
6/6/2012 -> 6/8/2012
6/5/2012 -> 6/8/2012

Assuming you want 6/9/2012 to also return 6/8/2012 (same week), this would work.
It get's the day of week of the current date and adds the difference between that and Friday which is hardcoded to a value of 6.
SET DATEFIRST 7;
declare #date date = '6/5/2012'
select dateadd(dd,6-datepart(dw,#date),#date) as Friday
If you want 6/9/2012 to return the next Friday, you just have to make a small modification:
SET DATEFIRST 7;
declare #date date = '6/9/2012'
set #date = dateadd(dd,1,#date) -- this adds a day to the date you inputted but doesn't matter since the function will always return to you a Friday
-- Sunday resets the week with datepart so adding a day to Saturday resets the week resulting in the next week being returned.
select dateadd(dd,6-datepart(dw,#date),#date) as Friday

Here's a function I created that seems to work. It does not change DATEFIRST and will give you the next date for the DOW. The function will return the date you passed in if it is on the DOW you are looking for.
CREATE FUNCTION [dbo].[func_NextDate]
(
#dt DATE,
#dow INT -- Use the day-of-week as defined by SQL Server (1=Sun, 7=Sat)
)
RETURNS DATE
AS
BEGIN
DECLARE #dtDiff INT = 7-((DATEPART(dw, #dt)+(7-#dow))%7)
IF #dtDiff = 7
SET #dtDiff = 0 -- Return the date if it is on the dow requested
RETURN DATEADD(dd, #dtDiff, #dt)
END

Related

Show only full weeks - SQL

how could I display only full weeks from my dataset? So if my week starts on Monday 1st of August to the 14th, that would be considered a full week. Whereas the one starting on the 8th is considered half and I'd like not to show it.
Many thanks in advance!
Table name:RRA
date column: seriesdate
My answer assumes that you want to select rows where the seriesdate value is in a week that is not the current week.
Assuming that your seriesdate column is indexed then a SARGable (i.e. fast) way to implement this filter is to just exclude rows with dates after the start-of-the-current-week. Like so...
Also...
Note that CURRENT_TIMESTAMP (the ISO SQL equivalent of SQL Server's GETDATE()) uses the database server's local timezone which might not be the timezone used by your data.
If so, replace DECLARE #now datetime2(7) = CURRENT_TIMESTAMP; with a date/time-literal like DECLARE #now datetime2(7) = '2022-08-10 12:34:56';
Note that most SQL Server setups will default to DATEFIRST 7 (Sunday).
SET DATEFIRST 1; -- https://learn.microsoft.com/en-us/sql/t-sql/statements/set-datefirst-transact-sql
DECLARE #now datetime2(7) = CURRENT_TIMESTAMP; -- or '2022-08-10 12:34:56'
-- https://stackoverflow.com/questions/7168874/get-first-day-of-week-in-sql-server
DECLARE #startOfThisWeek date = DATEADD( day, 1 - DATEPART( weekeday, #now ), #now );
SELECT
q.*
FROM
[RRA] AS q
WHERE
q.[seriesdate] < #startOfThisWeek

How can force SQL DateDiff function to stop rounding up?

I am working on a query that tries to count from an exact date to an exact date. Today is 2/16/2022. Between 6/30/2020 and 2/16/2022 19 months have gone by. My DateDiff query returns 20? How can I force DateDiff function to return 19?
select datediff(month, '6/30/2020', getdate())
As per documentationSQL Docs, datediff returns
The int difference between the startdate and enddate, expressed in the boundary set by datepart.
which in your example is the number of months from June '20 to February '22 which is indeed 20. User user716255's code is pointing into the right direction in that it uses the first of each month in question. If your intention however is to really know how many months elapsed between two dates, the code should be amended like so:
(sorry, need to correct my original answer, as I misread the code from the other answer)
declare #start date
declare #end date
set #start = '20200630'
set #end = '20220216'
select datediff(month, dateadd(day, -day(#start)+1, #start), dateadd(day, -
day(#end)+1,#end))+CASE WHEN DAY(#end)>DAY(#start) THEN 1 ELSE 0 END
(with dates written in a format more useful for our international readers...)
The original coude would fail if start date would i.e. be 31st of July and the end date in February (as -31+1 would lead to a date in January)
Here is the solution that worked for me.
declare #start date
declare #end date
set #start = '6/30/2020'
set #end = '2/16/2022'
select datediff(month, dateadd(day, -day(#start)+1, #start), dateadd(day, -day(#start)+1,#end))
link to fiddle

How to make a datepart() function in a view accept Monday as the first day of the week

For a webapplication I created the following view:
alter view [dbo].[vwBookingData]
as
select concat(rtrim(ltrim(str(datepart(year, bookingdata.booking_datetime)))), '-', rtrim(ltrim(str(datepart(week, bookingdata.booking_datetime))))) as WeekNumber,
bookingdata.booking_customerCode as ClientCode, customer.Name as ClientName, concat(bookingdata.booking_provider, concat('-', bookingdata.booking_system)) as ProviderCombo,
bookingdata.segments_carrierCode as CarrierCode, bookingdata.booking_datetime as BookingDate, bookingdata.booking_bookingId, flgConfirmed, flgFailed
from dbo.flights_bookingdata bookingdata
inner join dbo.Customer on Customer.Number = bookingdata.booking_customerCode
My problem is 1 specific part of the used query:
datepart(week, bookingdata.booking_datetime)
I have noticed the datepart() appears to take a week starts on Sunday rather than on Monday, this breaks the overview the view is supposed to generate.
Is there a way I can fix this within the query itself?
Perhaps you can try (I was right first with 1 not 2)
SET DATEFIRST 1;
At the top of your query
SET DATEFIRST 7; -- The Default
Select *
,WeedDay=DateName(DW,RetVal)
,WeekNo=DatePart(WK,RetVal)
From [dbo].[udf-Range-Date]('2016-10-01','2016-10-14','DD',1)
While
SET DATEFIRST 1;
Select *
,WeedDay=DateName(DW,RetVal)
,WeekNo=DatePart(WK,RetVal)
From [dbo].[udf-Range-Date]('2016-10-01','2016-10-14','DD',1)
Seeing that you can’t use the SET DATEFIRST option I would simply subtract one day from the datetime when you call the DATEPART function as follow:
DATEPART(WEEK, DATEADD(DAY, -1, bookingdata.booking_datetime))
With this function you can return the day of the week, starting from monday, in any server language or DATEFIRST setting:
-- =============================================
-- Author: Javier Cañon
-- Create date: 2019-04-23
-- Description: Return day of week without know of server SET DATEFIRST setting
-- =============================================
CREATE FUNCTION [dbo].[fnGetWeekDayFromMonday]
(
-- Add the parameters for the function here
#SomeDate DATE
)
RETURNS int
AS
BEGIN
DECLARE #SqlWeekDay INT, #ResultVar int;
SET #SqlWeekDay= DATEPART(dw, #SomeDate);
SET #ResultVar = ((#SqlWeekDay + ##DATEFIRST - 1 - 1) % 7) + 1;
-- Return the result of the function
RETURN #ResultVar;
END
GO

I need to create a function that will return number of day in a week on requested date

Something like this (which is not working)
CREATE FUNCTION dbo.udf_DayOfWeek
(#b_date DATETIME)
RETURNS VARCHAR(10)
AS
BEGIN
DECLARE #weekday VARCHAR(10)
IF (SELECT DATENAME(dw, #b_date)
RETURN (#weekday)
END;
GO
after using this
SELECT dbo.udf_DayOfWeek ('May 22, 2016');
GO
to return value of 1-7(number of a day in week)
I am using SQL Server 2014
You are going to want to use DATEPART() versus DATENAME() to get the numeric value, but this can be done inline and really doesn't need it's own function.
SELECT DATEPART(weekday,'May 22, 2016')
And to fix your function syntax...
CREATE FUNCTION dbo.udf_DayOfWeek (#b_date DATETIME)
RETURNS INT
AS
BEGIN
DECLARE #weekday INT
SELECT #weekday = DATEPART(WEEKDAY, #b_date)
RETURN (#weekday)
END
GO
DatePart for weekday uses the DateFirst setting, making it difficult to use consistently. The problem is, some places in the world consider Sunday to be the first day of the week, and other places consider Monday to be the first day of the week. Because of this ambiguity, SQL Server will use the datefirst setting of the login currently connected to the database. To see a list of datefirst settings, run this:
Select * From sys.syslanguages
You can manually set the DateFirst value that persists for the duration of the connection like this:
Set DateFirst 1
SELECT DATEPART(weekday,'May 22, 2016')
Set DateFirst 7
SELECT DATEPART(weekday,'May 22, 2016')
Note that the output of the previous code changes depending on the DateFirst setting.
If you want 1 to always represent Sunday, regardless of the user's language setting, you can use this:
Select DateDiff(Day, 6,#DateVariable) % 7 + 1
Using this information, you can create your user defined function like this:
CREATE FUNCTION dbo.udf_DayOfWeek
(#b_date DATETIME)
RETURNS int
AS
BEGIN
return (
Select DateDiff(Day, 6,#b_date) % 7 + 1
)
END;

SQL . The SP or function should calculate the next date for friday

I need to write a store procedure that will return a next friday date on a given date? for example - if the date is 05/12/2011, then it should return next friday date as 05/13/2011. If you pass, 05/16/2011, then it should return the date is 5/20/2011 (Friday). If you pass friday as the date, then it should return the same date.
I'd make this a scalar UDF as it is easier to consume the output.
CREATE FUNCTION dbo.GetNextFriday(
#D DATETIME
)
RETURNS DATETIME
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS
BEGIN
RETURN DATEADD(DAY,(13 - (##DATEFIRST + DATEPART(WEEKDAY,#D)))%7,#D)
END
This is for SQL Server 2008. To use in 2005, just change the date fields to your preference for datetime to date conversions. It also assumes you are not changing the default week begin value.
DECLARE #PassedDate date = '5/21/2011';
SELECT DATEADD(DAY,(CASE DATEPART(DW,#PassedDate) WHEN 7 THEN 6 ELSE 6 - DATEPART(DW,#PassedDate) END),#PassedDate);
Similar to the top answer, but without using ##DATEFIRST in the solution:
DECLARE #Today DATETIME = GETDATE(); -- any date
DECLARE #WeekdayIndex SMALLINT = DATEPART(WEEKDAY, #Today);
DECLARE #DaysUntilFriday SMALLINT = (13 - #WeekdayIndex) % 7;
DECLARE #UpcomingFridayDate DATETIME = DATEADD(DAY, #DaysUntilFriday, #Today);
SELECT #UpcomingFridayDate ;
Great solutions here, but I also recommend looking at time tables: you can generate them easily in Analysis server, and they can be indexed to be very fast, giving you lots of easy ways to get next week days (among other things).
You can find out more about them here
In our case, the same solution would be
Select MIN(PK_Date) from Time Where PK_Date > #SomeDate AND Day_Of_Week= 6
And of course when you're doing this for a large recordset, you can also do joins for maximum speed & efficiency.