I need to convert the Long value to a date time format.
Eg., Long value - 20080506015600658
datetime format - Tue May 06 01:56:00 IST 2008
Here's the ugly way to do it via string manipulation:
declare #start bigint
set #start = 20080506015600658
select CONVERT(datetime,
STUFF(STUFF(STUFF(STUFF(STUFF(STUFF(
t,15,0,'.'),
13,0,':'),
11,0,':'),
9,0,'T'),
7,0,'-'),
5,0,'-'))
from (select CONVERT(varchar(20),#start) as t) n
Which basically forces it to conform to the pattern YYYY-MM-DD'T'hh:mm:ss.mil before doing the conversion.
And here's the ugly as sin way to do it with maths:
declare #start bigint
set #start = 20080506015600658
select
DATEADD(year, (#start/10000000000000) - 1, --Because we already have 1 on starting date
DATEADD(month, (#start/100000000000)%100 - 1, --Because we already have 1 on starting date
DATEADD(day, (#start/1000000000)%100 - 1, --Because we already have 1 on starting date
DATEADD(hour, (#start/10000000)%100,
DATEADD(minute,(#start/100000)%100,
DATEADD(second,(#start/1000)%100,
DATEADD(millisecond,#start%1000,CONVERT(datetime2,'0001-01-01'))))))))
Related
I'm trying to write a financial report on our SAP B1 system using SQL Server Studio.
In my report I want the information to be calculated on a month to month basis. In my report I have #start date as #Startofcurrentfinancialyear, and my end as DD+30 (because there are 31 days in the month) However I am wanting to have mm+1 and dd-1 to bring me to the last day in the month.
I plan on changing the report for each month to give me the following.
MM+1 (for month 2) and MM+2 - DD 1 to give me the date range for month 2 etc.
Currently, I can make this go based on the following: MM+0, DD+30, then going ahead doing DD+60 etc and calculating for each month how many days they are, but this will give me problems with leap years.
DECLARE #Start DATETIME = DATEADD(MM,-0,#StartOfCurrentFinancialYear)
DECLARE #End DATETIME = DATEADD(DD,+30,#StartOfCurrentFinancialYear)
I expect to be able to define a month for each section and give the last day of the defined month based on the parameters given above.
If you want the end of month, then in all supported versions of SQL Server, you can do:
DECLARE #Start DATETIME = DATEADD(MONTH, -0, #StartOfCurrentFinancialYear);
DECLARE #End DATETIME = EOMONTH(#StartOfCurrentFinancialYear);
If you are using an unsupported version, you can do date arithmetic:
DECLARE #End DATETIME = DATEADD(day, -1,
DATEADD(month, 1,
DATEADD(day,
1 - DAY(#StartOfCurrentFinancialYear),
#StartOfCurrentFinancialYear
),
)
);
This does the following calculation:
Innermost subquery dateadd() moves to the first day of the month.
Middle subquery adds one month.
Outer query subtracts one day.
If you want start of the month and end of the month you can get it by using DateAdd function like :
DECLARE #Start DATETIME = DATEADD(DAY, (DAY(GETDATE()) * -1) + 1, GETDATE())
DECLARE #End DATETIME = DATEADD(MONTH,1,DATEADD(DAY, DAY(GETDATE()) * -1, GETDATE()))
SELECT #Start, #End
you can replace GETDATE() with your date variable so after your replacement the code should be something like this :
DECLARE #StartOfCurrentFinancialYear AS DATE = '31/aug/2019'
DECLARE #Start DATETIME = DATEADD(DAY, (DAY(#StartOfCurrentFinancialYear) * -1) + 1, #StartOfCurrentFinancialYear)
DECLARE #End DATETIME = DATEADD(MONTH,1,DATEADD(DAY, DAY(#StartOfCurrentFinancialYear) * -1, #StartOfCurrentFinancialYear))
SELECT #Start, #End
I want to get date from yyyy-mm-dd to yyyy-mm-dd in SQL.
Example: I have two parameter #startdate : 2015-12-28 and #enddate : 2016-01-02, and database in SQLServer, datatype is varchar(10)
DATE_ORDER
28-12-2015
30-12-1996
29-12-2016
30-12-1997
24-12-2015
27-12-1993
03-01-2016
01-01-1992
02-01-2016
etc...
Ok,now I want to get data from #startdate : 2015-12-28 and #enddate : 2016-01-02. I use SELECT * FROM TABLE_X WHERE DATE_ORDER >= #startdate AND DATE_ORDER <= #enddate . But the results are not what I expected. Here are the results I want
28-12-2015
30-12-1996
29-12-2016
30-12-1997
01-01-1992
02-01-2016
I think to solve this problem, I need to do two things :
First, get date range from #startdate to #enddate , in here 28/12/2015, 29/12/2015, 30/12/2015, 31/12/2015, 01/01/2016, 02/01/2016.
The second: get the date in database same in range 28/12, 29/12, 30/12, 31/12, 01/01, 02/01, ignoring the year.
Can you give me some ideas about this ?
Your actual format is "105-italian" find details here.
You can convert your existing VARCHAR(10)-values with this line to real datetime
SELECT CONVERT(DATETIME,YourColumn,105)
Next thing to know is, that you should not use BETWEEN but rather >=StartDate AND < NakedDateOfTheFollowingDay to check date ranges
So to solve your need Get date-range from 2015-12-28 to 2016-01-02 you might do something like this:
DECLARE #Start DATETIME={d'2015-12-28'};
DECLARE #End DATETIME={d'2016-01-02'};
SELECT *
FROM YourTable
WHERE CONVERT(DATETIME,YourDateColumn,105)>=#Start AND CONVERT(DATETIME,YourDateColumn,105)<#End+1
Attention Be aware, that the conversion lets your expression be not sargable. No index will be used.
Better was to store your date as correctly typed data to avoid conversions...
Try this query
SET DATEFIRST 1
DECLARE #wk int SET #wk = 2
DECLARE #yr int SET #yr = 2011
--define start and end limits
DECLARE #todate datetime, #fromdate datetime
SELECT #fromdate = dateadd (week, #wk, dateadd (YEAR, #yr-1900, 0)) - 4 -
datepart(dw, dateadd (week, #wk, dateadd (YEAR, #yr-1900, 0)) - 4) + 1
SELECT #todate = #fromdate + 6
;WITH DateSequence( Date ) AS
(
SELECT #fromdate AS Date
UNION ALL
SELECT dateadd(DAY, 1, Date)
FROM DateSequence
WHERE Date < #todate
)
--select result
SELECT * FROM DateSequence OPTION (MaxRecursion 1000)
So, after the 2nd or 3rd edit, it slowly becomes clear, what you want (i hope).
So you REALLY WANT to get the dates with the year beeing ignored.
As someone pointed out already, date-values are stored internally not as string, but as internal datatype date (whatever that is in memory, i don't know).
If you want to compare DATES, you cannot do that with ignorance of any part. If you want to, you have to build a NEW date value of day and month of given row and a hard coded year (2000 or 1 or whatever) for EVERY row.
SELECT * FROM TABLE_X WHERE convert(date,'2000' + substring(convert(char(8),convert(datetime, 'DATE_ORDER', 105),112),5,4),112) >= #startdate AND convert(date,'2000' + substring(convert(char(8),convert(datetime, 'DATE_ORDER', 105),112),5,4),112) <= #enddate
If your startdate and enddate go OVER sylvester, you have to do 2 queries, on from startdate to 1231, one from 0101 to enddate.
I'm using the Between command in SQL Server.
I need to find :
select * from MyTable where myDate
between getdate() and [1ms before tomorrow = 2012-02-26 :23:59:59:999]
I DON'T want [ 2012-02-27 :00:00:00:000] because future queries should use that value .
So I need 1 ms before tomorrow.
However - this is what I've tried but for some reason it refuse to give me the desire value !
and give me : 2012-02-26 23:59:59.997 + unpredictable results!
Why is that ? What am I missing ?
I want to get 2012-02-26 :23:59:59:999 !
Why not specify an exclusive range instead?
SELECT * FROM `MyTable`
WHERE `myDate` >= GETDATE() AND `myDate` < (tomorrow)
(I can't be bothered to figure out how to get tomorrow's DATETIME as I'm usually a MySQL guy, but I believe you already know how to do it.)
Otherwise you're stuck messing around with floating-point values of questionable accuracy.
The SQL Server DATETIME has an accuracy of 3.33ms - you'll always get the .997 as the closest value to a full hour. That's just the way it is, and you cannot change it in SQL Server 2005. Read all about it at Demystifying the SQL Server DATETIME datatype.
In SQL Server 2008, you can use the DATETIME2 datatype which has an accuracy of 100ns - so there you have up to 7 exact digits after the "seconds" decimal point.
Update: if you want to get .999 with a DATETIME2, you need to use:
DECLARE #dt2 DATETIME2
-- you need to cast GETDATE() to DATETIME2 - otherwise it's a DATETIME !
SET #dt2 = CAST(GETDATE() AS DATETIME2)
DECLARE #dt2_Added DATETIME2
SET #dt2_Added = DATEADD(d, DATEDIFF(d, 0, #dt2) + 1, 0)
SELECT DATEADD(ms, -1, #dt2_added)
Result:
2012-02-26 23:59:59.9990000
Update #2: things get stranger still.....
If I use SYSDATETIME() instead of GETDATE(), it gives me a DATETIME2 right from the get to - but if I do the calculation in one step:
DECLARE #dt2 DATETIME2
SET #dt2 = SYSDATETIME()
SELECT DATEADD(ms, -1, DATEADD(d, DATEDIFF(d, 0, #dt2) + 1, 0) )
I get the result of :
2012-02-27 00:00:00.000
but if I do the same calculation in two steps:
DECLARE #dt2 DATETIME2
SET #dt2 = SYSDATETIME()
DECLARE #dt2_Added DATETIME2
SET #dt2_Added = DATEADD(d, DATEDIFF(d, 0, #dt2) + 1, 0)
SELECT DATEADD(ms, -1, #dt2_added)
I get the expected result:
2012-02-26 23:59:59.9990000
This is indeed quite weird......
I want to create two DATETIME variables I can use to check with BETWEEN AND when given just one DATETIME in a stored procedure on SQL Server 2008.
So, when I get 2012/12/31 15:32:12 as input, I want to generate two new variables out of that, being #from = 2012/12/31 00:00:00 and #to = 2012/12/31 23:59:59.
These two variables are used to check if the records lie between them - that is, are on the same day as the input date.
I fooled around using CAST and CONVERT, but I don't really konw how to manipulate the dates in the way I want.
Should I do this another way? Or are there functions I'm not aware of?
Now it is version independedt
declare #from datetime, #to datetime
SET #from = convert(varchar, convert(datetime, '2012/12/31 15:32:12', 111), 112)
SET #to = DATEADD(day, 1, #from)
select * from yourtable where test date >= #from AND date < #to
You can;
declare #input datetime = '2012/12/31 15:32:12'
declare #from datetime = dateadd(day, 0, datediff(day, 0, #input))
declare #to datetime = dateadd(second, -1, dateadd(day, 1, #from))
>>>
2012-12-31 00:00:00.000 2012-12-31 23:59:59.000
Be careful of accuracy on your #to. 23:59:59.001 is a valid date but won't show up in your range if you subtract an entire second.
It is more common to set your #from and then use < #from + 1 instead of BETWEEN. (The plus adds whole days in SQL).
First convert your input date to a varchar using the appropriate date format(111 in this case), For the to date, append the midnight hour
Then cast your varchar back to datetime.
Example :
SELECT #from = CAST(CONVERT(VARCHAR(10), GETDATE(), 111) AS DATETIME)
,#to = CAST(CONVERT(VARCHAR(10), GETDATE(), 111)+' 23:59:59:997' AS DATETIME)
Here is a useful chart of datetime formats with brief explanations.
http://www.sql-server-helper.com/tips/date-formats.aspx
What would be the sql for the following,
I have a date of birth in an int field,
ie YYYYMMDD = 19600518
I would like to get the age.
None of the other answers are actually calculating age. They're calculating the number of year boundaries and not taking the birthday into account.
To calculate the age, you'll need to do something like this:
DECLARE #d DATETIME
SET #d = CONVERT(DATETIME, CONVERT(VARCHAR(8), 19600518), 112)
SELECT DATEDIFF(year, #d, GETDATE())
- CASE WHEN DATEADD(year, DATEDIFF(year, #d, GETDATE()), #d) <= GETDATE()
THEN 0 ELSE 1 END AS Age
Most of the other answers are not calculating age - just whole years (e.g. Jan 1 2009 is one "year" after Dec 31 2008). Thus, if you use most of the calculations on this page, you will return an incorrect age for half of the year, on average. Luke is the only person who has seen this but his answer strikes me as too complicated - there is an easier way:
Select CAST(DATEDIFF(hh, [birthdate], GETDATE()) / 8766 AS int) AS Age
(NOTE: Thanks go to 'Learning' for making a great catch on my original algorithm - this is a revision that uses hours instead of days)
Because the rounding here is very granular, this is almost perfectly accurate for every day of every year. The exceptions are so convoluted that they are almost humorous: every fourth year the age returned will be one year too young if we A) ask for the age before 6:00 AM, B) on the person's birthday and C) their birthday is after February 28th. Of course, depending on what time someone was born this might 'technically' be correct! In my setting, this is a perfectly acceptable compromise.
Here is a loop that prints out ages to show that this works.
Declare #age int;
Declare #BirthDate datetime;
Declare #Year int;
Set #Year = 2008;
WHILE (#Year > 1930)
BEGIN
-- Put today's date where you see '-03-18'
SET #BirthDate = CAST(Cast(#Year as varchar(4)) + '-03-18' AS DATETIME)
SELECT #age=CAST(DATEDIFF(hh, #BirthDate, GETDATE()) / 8766 AS int);
Print Cast(#Year as varchar) + ' Age: ' + Cast(#age as varchar);
Set #Year = #Year - 1;
END;
Finally, this is the version that will also convert Paul's integer date to a real date:
CAST(DATEDIFF(hh, Convert(Datetime, Convert(varchar(8), [birthdate]), 112), GETDATE()) / 8766 AS int) AS Age
DECLARE #dateSt VARCHAR(8)
DECLARE #startDt DATETIME
-- Set the start date string
SET #dateSt = '19600518'
-- Make it a DATETIME (the ISO way)
SET #startDt = CAST(SUBSTRING(#dateSt, 1, 4) + '-' +
SUBSTRING(#dateSt, 5, 2) + '-' +
SUBSTRING(#dateSt, 7, 2) AS DATETIME)
-- Age in Days
SELECT DATEDIFF(D, #startDt, getdate())
Age in years :
select datediff(YY, convert(datetime, convert(varchar, 19600518)), getdate())
[EDIT]
-- I forgot to declare the variables
declare #birthday datetime;
set #birthday = convert(datetime,convert(varchar, 19600518), 112);
declare #datetoday datetime;
set #datetoday = getdate();
select
(
CASE
WHEN dateadd(year, datediff (year, #birthday, #datetoday), #birthday) <= #datetoday
THEN datediff (year, #birthday, #datetoday)
ELSE datediff (year, #birthday, #datetoday) - 1
END) as age;
Here's a one-liner way to do it:
CONVERT(DATETIME, CONVERT(VARCHAR(8),19600518), 112)
But beware! This relies on T-SQL, and probably won't work in other SQL environments.
Please note that the "style" of 112 is simply the "ISO" date format of yyyymmdd. (Something I found in some CONVERT documentation.)
This is a reason why you should NOT ever store dates as anything except a datetime datatype. The best fix is to change your datatype and convert all the dates once (wouldn't be surprised if there are few invalid ones in there either). then you never have to do these workarounds again.
I worked it out and got same as #Learning
select dob, datediff(year, convert(datetime, convert(varchar(8),[dob])) ,getdate()) as age
from [mytable]
where IsDate(convert(varchar(8),[dob])) = 1
NB. I needed the IsDate as well as there were some invalid dates in the data.
Edit. Here is an article from SQLServerCentral on calculating age.