Compare SQL server datetime column to year month? - sql-server

SELECT * FROM TABLE
WHERE YEAR(MDTFlgtStart)=YEAR(GETDATE()) AND MONTH(MDTFlgtStart)=MONTH(GETDATE())
Above code it compares with present year and month with the column year and month.
But do we have any chance we can give year=2012 month =3
or year =2011 month=5

You could declare variables:
DECLARE #YEAR AS INT
DECLARE #MONTH AS INT
SET #YEAR = 2012
SET #MONTH = 3
SELECT *
FROM TABLE
WHERE YEAR(MDTFlgtStart)=#YEAR AND MONTH(MDTFlgtStart)=#MONTH
You can wrap the above in a procedure for re-usability....

You can just use parameters for those values. As a bonus, avoiding functions against the column will help assist a seek if an index exists on the column (of course SELECT * means it will likely end up as a full scan anyway, or a range scan and a bunch of lookups)...
-- these would be input parameters for your stored procedure
DECLARE #y INT = 2011, #m INT = 5;
-- now have a date variable:
DECLARE #dt DATE = DATEADD(MONTH, #m-1, DATEADD(YEAR, #y-1900, 0));
SELECT ... FROM dbo.tablename
WHERE MDTFlgtStart >= #dt
AND MDTFlgtStart < DATEADD(MONTH, 1, #dt);
Also you should stop inviting whoever named these columns to lunch, because I have to assume they're not very nice.

Related

What does this SQL function do?

I'm not sure if I get this right. Please someone explain to me. I don't know what deatiles should I add to shis function. I gues somwone who knows sql well will know this easily
declare #date datetime = '2016-05-01',
#ndays INT = 11,
#country NVARCHAR(2)
BEGIN
IF #date IS NULL
BEGIN
SET #date = GETDATE();
END
IF #country IS NULL
BEGIN
SET #country = 'HU';
END
DECLARE #count INT = 1
DECLARE #newdate datetime
DECLARE #firstdayofmonth date = DATEADD(month, DATEDIFF(month, 0, #date), 0)
WHILE DATEPART(weekday,#firstdayofmonth) in (7,1)
BEGIN
SET #firstdayofmonth = DATEADD(DAY, 1, #firstdayofmonth)
END;
SET #newdate = #firstdayofmonth
WHILE #count < #ndays
BEGIN
SET #newdate = DATEADD(DAY, 1, #newdate)
IF (DATEPART(WEEKDAY, #newdate) not in (1,7))
SET #count += 1;
END
select #newdate
END
I get that this is about declaring a date. The firstdayofmonth calculatio is confusing in it.
This is clearly no mysql code weekday goes from 0 to 6. Also you can't declare variables that way.
Also you should have posted the whole code.
AS for your code:
The first While Clause searches for the first Monday in a Month.
The second counts all Working Days (Monday till Friday) of that chosen Month.
With the first variables, you can manipulate which Month, but what that country has to do with it I can only guess that you have a list of all public holiday fur Hungary.
#newdate becomes the first weekday of the month (Monday-Friday). If the month starts on a weekend (Saturday or Sunday), it shifts up until Monday; otherwise it stays the same. As for the second part, #count looks like it ends up being the number of weekdays in the first eleven days since the start of the first weekday.

Is there an easy way to determine the next business day from a date with weekends and holidays included in the calculation?

I have a future table which shows holidays and weekends along with calendar dates and I want to add a next business day field to that based on Holidays and Weekends.
For example: January 2nd 2020 is a holiday and so is January 1st. January 1st 2020 is a wednesday, so the next business day should be January 3rd. (skips the 2nd, friday is a business day).
Is there an easy function or loop which can do this simply? I only need to do it once so i'm not worried too much about not utilizing a set operation.
I had created what i assumed was the worlds worst case statement, but I realized that solution was just clunky and not supportable.
I don't have the reputation to comment but from what I have gathered... no, there is not a function provided by SQL Server but you can write a simple function like the one done in this post Declare date, then add next business day
Good luck!
Thanks , I just used a derived subquery to allow incorrect dates to populate when there was a holiday to consider, then rolled those up to another layer and added an extra day.
Not the most elegant, but worked for my scenario.
select
a.date
,a.day
,a.firstOfMonth
,a.MonthName
,a.week
,a.dayofWeek
,a.hldyInd
,a.weekendInd
,case when a.Nbdtemp IN ('2020-01-01','2020-01-02','2020-01-20','2020-05-25','2020-07-03','2020-11-26','2020-12-25') then dateadd(day,1,nbdtemp) else Nbdtemp end as NxtBusinessDay
into #final
from
(
select t.*,
case when t.dayofweek not in ('Friday','Saturday') and t.HldyInd = 'N' then DATEADD(day,1,date)
when t.dayofweek = 'Friday' and t.hldyind = 'N' then dateadd(day,3,date)
when t.dayofweek = 'Saturday' and t.hldyind = 'N' then dateadd(day,2,date)
when t.hldyind = 'Y' then dateadd(day,1,date) end as Nbdtemp
from #updtdim t
) as a
The easy way is create Holidays table, and enter each holiday every year. After that, you can easy to give a day and find the next working day.
Here is my function to get how many working days between start and end day. You can easy to modify and get next business day.
CREATE TABLE [dbo].[Holidays](
[Date] [date] NULL,
[Description] [varchar](100) NULL
) ON [PRIMARY]
GO
CREATE FUNCTION [dbo].[GetWorkingDays]
(
#StartDate date,
#EndDate date
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE #ResultVar int = 0;
DECLARE #dt date = #StartDate;
WHILE #EndDate >= #dt BEGIN
IF DATEPART(WEEKDAY,#dt) < 6 BEGIN
IF NOT EXISTS(SELECT Date FROM Holidays WHERE Date=#dt) BEGIN
SET #ResultVar = #ResultVar + 1;
END
END
SET #dt = DATEADD(DAY,1,#dt);
END
RETURN #ResultVar;
END
Try something like this:
create table dbo.HolidayList(Holiday date)
insert into HolidayList(Holiday)values
('2019-07-01T00:00:00.000'),('2019-07-09T00:00:00.000'),('2019-08-01T00:00:00.000'),
('2019-08-02T00:00:00.000'),('2019-08-05T00:00:00.000'),('2019-09-02T00:00:00.000'),
('2019-10-14T00:00:00.000'),('2019-11-11T00:00:00.000'),('2019-12-25T00:00:00.000'),
('2019-12-26T00:00:00.000'),('2020-01-01T00:00:00.000'),('2020-02-10T00:00:00.000'),
('2020-02-17T00:00:00.000'),('2020-03-17T00:00:00.000'),('2020-04-10T00:00:00.000'),
('2020-04-13T00:00:00.000'),('2020-04-23T00:00:00.000'),('2020-05-18T00:00:00.000'),
('2020-05-25T00:00:00.000'),('2020-06-24T00:00:00.000'),('2020-07-01T00:00:00.000'),
('2020-07-09T00:00:00.000'),('2020-07-30T00:00:00.000'),('2020-07-31T00:00:00.000')
go
create function dbo.IsWeekday(#Date date) returns bit
begin
return case when DATEDIFF(day,'0001-01-01T00:00:00.000',#Date)
% 7 < 5 then 1 else 0 end
end
go
create function dbo.IsHoliday(#Date date)returns bit
begin
return case when #Date in(select Holiday from HolidayList) then 1 else 0 end
end
go
create function dbo.IsWorkDay(#Date date)returns bit
begin
return case when dbo.IsWeekday(#Date)=1 and dbo.IsHoliday(#Date)=0 then 1 else 0 end
end
go
create function dbo.WorkdayFollowing(#Date date)returns date
begin
declare #D date = DATEADD(day,1,#date)
while dbo.isworkday(#D)=0
begin
set #D = DATEADD(day,1,#D)
end
return #D
end
go
declare #d date = '2019-06-01T00:00:00.000'
while #d < '2019-09-01T00:00:00.000'
begin
set #d=DATEADD(day,1,#d)
select #d, dbo.workdayfollowing(#d)
end

Convert epoch to datetime

On a table I have a bigint column that stores a timestamp with a microsecond precision like:
636453251396217655
636453251398405201
636453251592389899
636453251668326820
I have to build a script that, if that date is older than a week, the row must moved to another table.
I tried to convert to date using:
CREATE FUNCTION [dbo].[UNIXToDateTime] (#timestamp bigint)
RETURNS datetime
AS
BEGIN
DECLARE #ret datetime
SELECT #ret = DATEADD(second, #timestamp, '1970/01/01 00:00:00')
RETURN #ret
END
and used like:
select dbo.UNIXToDateTime(636453251396217655)
but because of the bigint my script crash because:
Arithmetic overflow error during expression conversion in int data
type
I can lose precision, the important is the date part that is the main part of the sql filter.
Demo: http://sqlfiddle.com/#!6/24f05/1
There's an answer here for converting with epoch values:
CREATE FUNCTION [dbo].[fn_EpochToDatetime] (#Epoch BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE #Days AS INT, #MilliSeconds AS INT
SET #Days = #Epoch / (1000*60*60*24)
SET #MilliSeconds = #Epoch % (1000*60*60*24)
RETURN (SELECT DATEADD(MILLISECOND, #MilliSeconds, DATEADD(DAY, #Days, '1/1/1970')))
END;
You can use that function but simply divide your epoch values. As you are fine with the loss of fidelity, this will suit your needs perfectly. For example:
DECLARE #epoch BIGINT = 636453251396217655
SELECT dbo.[fn_EpochToDatetime](#epoch/100000)

How to filter result only by month and year?

I use SQL SERVER 2012.
I have stored prcedure:
ALTER PROCEDURE [dbo].[SP_TEST_TLP]
#DateFrom date,
#DateTo date
AS
BEGIN
SET NOCOUNT ON;
select *
from Clients
WHERE DateReview between (#DateFrom) and (#DateTo)
END
As you can see I pass two parameters to stored procedure above and those parameters I use to filter the result in where clause.
My problem is that I need to filter result only by month and year.
For example, if I have passed those parameters:
#DateFrom date = '2016-05-15' ,
#DateTo date = '2016-10-09'
According to stored procedure I will get result between dates above.But I need to get rows from start of the month 05 and end of the month 10 i,e the result should be equivalent to those params:
#DateFrom date = '2016-05-01'
#DateTo date = '2016-10-31'
How can I get the desired result?
You can also use EOMONTH function
select *
from Clients
WHERE DateReview between DATEADD(DAY,1,EOMONTH(#DateFrom,-1) ) and EOMONTH(#DateTO)
Try this :
Here
DATEADD(dd,-(DAY(#DateFrom)-1),#DateFrom) this will give months start date i.e '2016-05-01'
And
DATEADD(dd,-(DAY(DATEADD(mm,1,#DateTo))),DATEADD(mm,1,#DateTo)) will give month end date i.e '2016-10-31'
ALTER PROCEDURE [dbo].[SP_TEST_TLP]
#DateFrom date,
#DateTo date
AS
BEGIN
SET NOCOUNT ON;
SET #DateFrom = DATEADD(dd,-(DAY(#DateFrom)-1),#DateFrom)
SET #DateTo = DATEADD(dd,-(DAY(DATEADD(mm,1,#DateTo))),DATEADD(mm,1,#DateTo))
Updated ---^
select *
from Clients
WHERE DateReview between (#DateFrom) and (#DateTo)
END
Here is one way:
select *
from Clients
where DateReview >= dateadd(day, 1 - day(#DateFrom), #DateFrom) AND
DateReview < dateadd(month, 1, dateadd(day, 1 - day(#DateTo), #DateTo))
This method allows the query to make use of an index on DateReview. You could also do this as:
where year(DateReview) * 100 + month(DateReview)
between year(#DateFrom) * 100 + month(#DateFrom) and
year(#DateTo) * 100 + month(#DateTo)
You can use EOMonth() function
ALTER PROCEDURE [dbo].[SP_TEST_TLP]
#DateFrom date,
#DateTo date
AS
BEGIN
SET NOCOUNT ON;
select *
from Clients
WHERE DateReview between Dateadd(d,1,EOMonth(#DateFrom,-1)) and EOMonnth(#DateTo)
END

Reading a string expression with parameters and executing the expression as date

I am trying to create dynamic code for date calculation in SQL stored procedures but am having problems executing string expressions and parameters as date expressions.
I want to hold generic string expressions in a table that will create the dates according to the value of the parameters.
for example this is a generic expression :
DATEADD(#TimeResolution, -#IterationN, #CurrentCalc)
as you can see these generic expressions are composed out of parameters to.
in the stored procedures I intend to declare the variables that are in the expression and assign values to them using a select statement from a different table.
the problem is that after deriving these string values and writing the expression it does not give me the date I want but fails.
so for example if I write the following code
declare #Today date
declare #LastYear date
set #Today = getdate()
set #LastYear = DATEADD(year, -1, #Today)
select #Lastyear
it works fine and I will get last year's date.
but when I try something like this :
declare #Today date
declare #LastYear date
declare #Timeresolution varchar(5)
select #Timeresolution = [Timeresolution] from dbo.mytable where rule_id=1//Timeresolution is a varchar column in my table holding the values 'year' or 'month'
declare Iteration int
select #Iteration = [Iteration] from dbo.mytable where rule_id=1 //Iteration is a int column in my table holding the values 1 or 2, or 3
set #Today = getdate()
set #LastYear = DATEADD(Timeresolution , -Iteration , #Today)
select #Lastyear
this gives me a conversion error.
Is there a way to create such dynamic date expressions?
It isn't possible to use a variable for the interval in DATEADD, but you can do something like this:
IF #Timeresolution = 'year'
BEGIN
SET #LastYear = DATEADD(year, -#Iteration , #Today)
END
IF #Timeresolution = 'month'
BEGIN
SET #LastYear = DATEADD(month, -#Iteration , #Today)
END

Resources