Microsoft SQL Server 2005 - using the modulo operator - sql

So I have a silly problem, I have not used much SQL Server before, or any SQL for that matter. I basically have a minor mathematical problem that I need solved, and I thought modulo would be good.
I have a number of dates in the database, but I need them be rounded off to the closest [dynamic integer] (could be anything from 0 to 5000000) which will be input as a parameter each time this query is called.
So I thought I'd use modulo to find the remainder, then subtract that remainder from the date.
If there is a better way, or an integrated function, please let me know!
What would be the syntax for that? I've tried a lot of things, but I keep getting error messages like integers/floats/decimals can't be used with the modulo operators. I tried casting to all kinds of numeric datatypes.
Any help would be appreciated.

Create function [GetNDates]
(
#NumberOfDates int,
#StartDate DateTime,
#EndDate DateTime
)
Returns #DatesTable table
(
MyDate DateTime
)
As
Begin
Declare #TotalDays int
Declare #Increment int
Declare #Counter int
Declare #DateCounter DateTime
SET #Counter = 0
SELECT #DateCounter = #StartDate
SELECT #TotalDays = DATEDIFF(day, #StartDate, #EndDate)
SET #Increment = #TotalDays / #NumberOfDates
WHILE #Counter < #NumberOfDates
BEGIN
SET #DateCounter = DATEADD(Day, #Increment, #DateCounter)
INSERT INTO #DatesTable (MyDate) VALUES (#DateCounter)
SET #Counter = #Counter + 1
END
Return
End
GO
select * from dbo.GetNDates(40, '1/1/2010', '12/31/2010')

Related

Date won't change after using DATEADD() function in SQL Server 2017

I have a date stored in a string (#cnp=1051597991234) the date being 051597 representing 5/15/1997. I am using the following code to set a date variable with the needed value, in the end to compute the current age.
I used the debugger but somehow it ends up being not set and the diff also returning null.
If someone could help I would be very grateful
declare #cnp varchar(30) = 1051597991234;
declare #age int;
declare #dateBorn date = CAST('1900-01-01' AS DATETIME);
declare #dayBorn int;
declare #monthBorn int;
declare #yearBorn int;
set #dayBorn = cast(substring(#cnp, 2, 2) as int) - 1;
set #monthBorn = cast(substring(#cnp, 4, 2) as int) - 1;
set #yearBorn = cast(substring(#cnp, 6, 2) as int);
set #dateBorn = dateadd(yyyy, #yearBorn, #dateBorn);
set #dateBorn = dateadd(mm, #monthBorn, #dateBorn);
set #dateBorn = dateadd(dd, #dayBorn, #dateBorn);
set #age = datediff(year, getdate(), #dateBorn);
It's declaration problem. Just change this
declare #cnp = 1051597991234
with this
declare #cnp nvarchar(20) ='1051597991234'
and also change the sequence for as from date will be date of birth
set #age =datediff(year,#dateBorn,getdate());
Can I suggest using the DATEFROMPARTS function?
So:
DECLARE #dateBorn DATE =
DATEFROMPARTS(
CAST('19' + SUBSTRING(#cnp,6,2) AS INT)
,CAST(SUBSTRING(#cnp,2,2) AS INT)
,CAST(SUBSTRING(#cnp,4,2) AS INT)
);
DECLARE #age INT =
DATEDIFF(YEAR, GETDATE(), #dateBorn);
Please note that the birthdate strings you have are not Y2K safe, which is why I've put a constant in to assume that they were in the 20th century.
Also note that your dates are in American format, with the month first, day second, and year third.

Data operations

I wrote a stored procedure who take a reference date, and add a hour to this element.
Here is my line doing the operation :
DATEADD(day, DATEDIFF(DAY, 0, #conductor_date), [HOUR])
For example, whith #conductor_date = '2015-10-15' and [HOUR] = 23:00 it works and generate me a date like that : '2015-10-15:23:00:00'
I face a logical issue when the value [HOUR] is more than 24. In fact, to solve my problem I need to generate '2015-10-16:00:40:00' when [HOUR] = 24:40
Actualy with this values, I face the logical following exception :
The conversion of a varchar data type to a datetime data type resulted
in an out-of-range value.
To sum up, I need to take care of hours that are more than '23:59' and switch to the next day :
DECLARE #conductor_date datetime
DECLARE #hour varchar(5)
SET #conductor_date = '2015-10-15'
SET #hour = '24:40'
SELECT DATEADD(day, DATEDIFF(DAY, 0, #conductor_date), #hour)
Expected : 2015-10-16:00:40:00
According to the documentation, date / time types don't support times larger then 23:59:59.9999999. You have to do manual string parsing for this.
First you need to extract the total hours, divide that by 24 to get total days. Then calculate leftover hours, and with that reconstruct your time offset.
With these in hand, you can build your required output value:
DECLARE #v VARCHAR(20) = '24:40'
DECLARE #start VARCHAR(20) = '2015-10-15'
DECLARE #days INT
DECLARE #leftover INT
SET #leftover = CAST(LEFT(#v, 2) AS INT)
SET #days = #leftover / 24
SET #leftover = #leftover - #days * 24
SET #v = CAST(#leftover AS VARCHAR(2)) + SUBSTRING(#v, 3, 20)
SELECT DATEADD(DAY, #days + DATEDIFF(DAY, 0, #start), #v)
Here's a working SQLFiddle.
This supports time string that start with HH (leading zeros) with any valid accuracy (HH:mm:ss.fffffff).
You can split your #hour field into hours and minutes and add them separately:
DECLARE #conductor_date datetime
DECLARE #hour varchar(5)
DECLARE #hours int
DECLARE #minutes int
DECLARE #offset datetime
SET #conductor_date = '2015-10-15'
SET #hour = '24:40'
SET #hours = cast(left(#hour, 2) as int)
SET #minutes = cast(right(#hour, 2) as int)
SET #offset = dateadd(day, datediff(day, 0,#conductor_date), 0) -- the begin of the day
SELECT DATEADD(hour, #hours, dateadd(minute, #minutes, #offset))
Of course all can be done in one line but for sake of visualization I have put it into separate statements.
You may try below query
SELECT DATEADD(MINUTE,(LEFT(#hour,2)*60+RIGHT(#hour,2)),#conductor_date)

Error when running SQL stored procedure coversion failed when converting date and/or time from character string

DECLARE #i varchar(13)
DECLARE #Year varchar(30)
SET #i = 2
SET #Year = 2013
SELECT SUM(CAST([totalAfterMultiplier] as money)) as 'totalAfterMultiplier' FROM [postfinanceAfterMultiplier]
WHERE CAST([ORDER] as date) >= '01/'+#i+'/'+ #Year +'' AND CAST([ORDER] as date) <= '31/'+#i+'/'+ #Year +''
I am getting this error: Conversion failed when converting date and/or time from character string.
All values in the database are varchar(50)
I have looked at the other posts and can't seem to get it working
Thank you all for your help
Don't store dates as varchar.
if you want to convert to date from string 'dd/mm/yyyy', use explicit format 103, like select convert(date, '01/12/2013', 103). See other formats here - CAST and CONVERT (Transact-SQL)
I found that the following solution works:
DECLARE #i varchar(13)
DECLARE #Year varchar(30)
SET #i = 2
SET #Year = 2013
SELECT SUM(CAST([totalAfterMultiplier] as money)) as 'totalAfterMultiplier' FROM [postfinanceAfterMultiplier]
WHERE MONTH([ORDER]) = #i AND YEAR([ORDER]) = #Year

Count number of weeks in between days in SQL server 2005

I am here again for some help. This is what I am trying to do. I have a function or sp that takes 3 parameters. startdate, enddate, and dayofweek (m, t, w, etc), need to count how many weeks are in between the start and end date.
Example, if I pass startday=2011-05-02, enddate=2011-05-10, and dayofweek as Tuesday, it should count 2, if I pass dayofweek as wednesday then it should count 1.
I am able to work using this code, is there any better way to do this? The ClosingStartDate is being adjusted to the correct start date based on the dayofweek used. So basically, the code is adding 1 week to the runningdate and running date is adjusted according to the week is used.
Any other way to do it without the while..loop.???
declare #NoofPeriods int
declare #runningdate datetime
set #runningdate = #ClosingStartDate
set #NoofPeriods=0
while (#runningdate <= #NextStatementClosingdate)
begin
set #NoofPeriods=#NoofPeriods+1
set #runningdate = Dateadd(day,7,#runningdate)
end
It is already built in to SQL 2005.
SELECT DATEDIFF(week, #startdate, #enddate)
I'm probably not dead on with the SQL Server syntax, but logic like this should work. Basically use modulo-7 arithmetic to determine how many "odd" days you have at the start of the period, and whether these include one of your chosen weekdays (as determined by your dayofweek) or not.
#diffInDays = SELECT DATEDIFF(day, #startdate, #enddate)
#startDateDay = SELECT DATEPART(weekday, #startdate)
set #diffInWholeWeeks = #diffInDays / 7
set #diffRemainderDays = #diffInDays % 7
if #diffRemainderDays >= ( ( #dayofweek - #startDateDay ) % 7 )
begin
set #extraWeek = 1
end
else
begin
set #extraWeek = 0
end
set #answer = #diffInWholeWeeks + #extraWeek
#slothrop's answer is almost dead on, so I am going to base this on that code and upvote that answer.
Okay this comment was wrong (please ignore):
Because days are from 1-7 instead of 0-6, we need to account for it. I do this by subtracting one after our second modulous. I haven't tested all scenarios, but it seems to work.
What was messing me up was the shift of the week. Add 7 to the dayofweek to make sure the mod works.
This should work,
--Setup
DECLARE #dayofweek int = 4
DECLARE #startdate datetime = '5/2/2011'
DECLARE #enddate datetime = '5/10/2011'
--Solution
DECLARE #diffInDays int = DATEDIFF(day, #startdate, #enddate);
DECLARE #startDateDay int = DATEPART(weekday, #startdate);
DECLARE #extraWeek int = 0;
DECLARE #diffInWholeWeeks int = #diffInDays / 7
DECLARE #diffRemainderDays int = #diffInDays % 7
if #diffRemainderDays >= ( ( #dayofweek + 7 - #startDateDay ) % 7 )
set #extraWeek = 1
DECLARE #answer int = #diffInWholeWeeks + #extraWeek
SELECT #answer
Note: I'm not sure the inline setting of declarations is supported in 2005. If so, just use a SET or SELECT statement to set the values.

Calculating variances on dates in T-SQL

Guys, I am trying to write a stored procedure in T-SQL (SQL Server) that will select records based on a date field, keeping a variance of minutes in mind. Something like this:
CREATE PROCEDURE spGetCustomers(#DateRange DATETIME, #Variance int) AS
-- The next line is where I need help
-- I'm trying to subtract X amount of minutes from the date
-- So if #Variance = 4 AND #DateRange = '6/10/2009 1:15pm'
-- Then #StartDate should equal '6/10/2009 1:11pm'
DECLARE #StartDate = #DateRange - #Variance
-- I also need an #EndDate, which will be X amount of minutes
-- in the future. So if #Variance = 4 AND #DateRange = '6/10/2009 1:15pm'
-- Then #EndDate should equal '6/10/2009 1:19pm'
DECLARE #EndDate = #DateRange + #Variance
SELECT * FROM Customers WHERE Created BETWEEN #StartDate AND #EndDate
Hopefully this makes sense and someone can help me out! Thanks in advance
Check this out:
http://msdn.microsoft.com/en-us/library/ms186819(SQL.90).aspx
The DATEADD function allows you to add virtually any part of a date to another date object, it should be everything you need.
So basically do:
SELECT DATEADD(second, #Variance, #DateRange)
The following script provides an example that should get you started.
create table tmp_Customers
(
ID int identity(1,1),
CreatedDate datetime default getDate() not null,
Description varchar(15)
);
go
insert into tmp_Customers(Description) values('SomeData');
insert into tmp_Customers(Description) values('SomeData2');
insert into tmp_Customers(Description) values('SomeData3');
go
create procedure usp_GetCustomers
#iVarianceMinutes int,
#iDateRange datetime
as
set nocount on
declare #startDate datetime
declare #endDate datetime
--Define the date ranges for the select query
set #startDate = dateAdd(minute,-#iVarianceMinutes,#iDateRange)
set #endDate = dateAdd(minute,#iVarianceMinutes,#iDateRange)
--Get the Customers that were created within this time range.
SELECT *
FROM tmp_Customers
WHERE CreatedDate >= #startDate and CreatedDate < #endDate
return(0);
go
--Execute the procedure
declare #testDate datetime;
set #testDate = getDate();
exec usp_GetCustomers 5,#testDate
--drop procedure usp_GetCustomers
--drop table tmp_Customers