DATEDIFF() to just return age with 2 decimal points - sql

I have a SELECT statement requesting the age of he individual when a test was made:
SELECT
DATEDIFF(dd,BIRTH_DATE,TEST_DATE)/365.25 [Age at Result]
FROM TABLE
WHERE ID = '100'
The result comes out like 2.056125.
I saw on another post to convert to seconds and divide by 86400.0, but I was still getting 6 decimal points.
What I was looking back was to get the age as 2.05 or even round to 2.00.
Thanks

You can cast to a decimal with the precision you want:
SELECT CAST(DATEDIFF(day, BIRTH_DATE, TEST_DATE)/365.25 as DECIMAL(10, 2)) as [Age at Result]
FROM TABLE
WHERE ID = 100;
Note: I removed the single quotes around "100". Only use single quotes if it the id is a string.

I would use the following -
DECLARE #TestDate DATETIME = GETDATE()
DECLARE #BirthDate DATETIME = '1995-06-06 08:00:00.000'
SELECT CAST(DATEDIFF(dd,#BirthDate,#TestDate)/365.25 AS DECIMAL(10, 2)) [Age at Result]

Related

Dividing numeric data types result as different scaled numeric type [duplicate]

I keep getting this error message everytime I run this query:
Msg 8115, Level 16, State 8, Line 33
Arithmetic overflow error converting numeric to data type numeric.
The statement has been terminated.
But if I change the create table to (7,0), I don't get the error message.But I need my data to be displayed as a decimal. I have tried 8,3 does not work.
Is there any one who can help me work this?Any help will be greatly appreciated.
DECLARE #StartDate AS DATETIME
DECLARE #StartDate_y AS DATETIME
DECLARE #EndDate AS DATETIME
DECLARE #temp_y AS DATETIME
SET #temp_y = Dateadd(yy, Datediff(yy, 0, Getdate()), 0)
SET #StartDate_y = Dateadd(dd, 1 - Datepart(dw, Dateadd("ww", -2, #temp_y)),
Dateadd("ww", -2, #temp_y))
SET #StartDate = Dateadd(dd, 1 - Datepart(dw, Dateadd("ww", -2, Getdate())),
Dateadd("ww", -2, Getdate()))
SET #EndDate = Dateadd(dd, 6, #StartDate)
--temp table to hold all cities in list
CREATE TABLE ##temp
(
city VARCHAR(50)
)
INSERT INTO ##temp
VALUES ('ABERDEEN'),
('CHESAPEAKE'),
('Preffered-Seafood/CHICAGO'),
('Preffered-Redist/CHICAGO'),
('CLACKAMAS'),
('COLUMBUS'),
('CONKLIN'),
('DENVER'),
('FORT WORTH'),
('HANOVER PARK'),
('JACKSONVILLE'),
('LAKELAND'),
('MONTGOMERY'),
('PFW-NORTHEAST'),
('PFW-SOUTHEAST'),
('RIVERSIDE'),
('TRENTON,CANADA'),
('VERNON')
--temp to hold data for the cities
CREATE TABLE #temp
(
city VARCHAR(50),
ytdshipments INT,
ytdtotalweight DECIMAL(7, 2) NOT NULL,
ytdtotalcharges DECIMAL (7, 2) NOT NULL
--YTDRevperPound decimal (7,2) not null
)
INSERT INTO #temp
SELECT ##temp.city,
0,
0,
0
FROM ##temp
INSERT #temp
-- YTD shipments/Charges/Weight by city
SELECT city = CASE
WHEN nameaddrmstr_1.city IN( 'ABERDEEN', 'CHESAPEAKE', 'CHICAGO'
,
'CLACKAMAS',
'COLUMBUS', 'CONKLIN', 'DENVER',
'FORT WORTH',
'HANOVER PARK', 'JACKSONVILLE',
'LAKELAND'
,
'MONTGOMERY'
,
'RIVERSIDE', 'TRENTON', 'VERNON' )
THEN
CASE
WHEN
nameaddrmstr_1.city = 'CHICAGO'
AND h.shipr = 'PREFRESVS' THEN 'Preffered-Redist/CHICAGO'
WHEN
nameaddrmstr_1.city = 'TRENTON'
AND nameaddrmstr_1.city = 'CA' THEN 'TRENTON,CANADA'
ELSE
nameaddrmstr_1.city
END
ELSE 'Other'
END,
ytdshipments = COUNT(CONVERT(VARCHAR(10), h.dateshipped, 101)),
ytdtotalweight =SUM(CASE
WHEN h.totaldimwgt > h.totalwgt THEN h.totaldimwgt
ELSE h.totalwgt
END),
ytdtotalcharges = SUM (cs.totalestrevcharges)
--YTDRevperPound = convert(decimal(7,2),sum (cs.TotalEstRevCharges )/sum( CASE WHEN h.TotalDimWGT > > h.TotalWGT THEN h.TotalDimWGT ELSE h.TotalWGT END ))
FROM as400.dbo.hawb AS h WITH(nolock)
INNER JOIN as400.dbo.chargesummary AS cs
ON h.hawbnum = cs.hawbnum
LEFT OUTER JOIN as400.dbo.nameaddrmstr AS nameaddrmstr_1
ON h.shipr = nameaddrmstr_1.nameaddrcode
WHERE h.dateshipped >= '01/01/2010'
AND h.dateshipped <= '12/19/2010'
--WHERE H.DateShipped >= >= #StartDate_y AND H.dateshipped <= #EndDate
AND h.cust IN( 'DARDENREED', 'MAINEDARDE', 'MBMRIVRSDE', 'MBMCOLUMBS',
'MBMLAKELND', 'MBMFTWORTH', 'SYGMACOLUM', 'SYGMANETW6',
'MAI215', 'MBMMNTGMRY' )
GROUP BY CASE
WHEN nameaddrmstr_1.city IN( 'ABERDEEN', 'CHESAPEAKE', 'CHICAGO', 'CLACKAMAS',
'COLUMBUS', 'CONKLIN', 'DENVER', 'FORT WORTH',
'HANOVER PARK', 'JACKSONVILLE', 'LAKELAND',
'MONTGOMERY'
,
'RIVERSIDE', 'TRENTON', 'VERNON' ) THEN CASE
WHEN
nameaddrmstr_1.city = 'CHICAGO'
AND h.shipr = 'PREFRESVS' THEN 'Preffered-Redist/CHICAGO'
WHEN
nameaddrmstr_1.city = 'TRENTON'
AND nameaddrmstr_1.city = 'CA' THEN 'TRENTON,CANADA'
ELSE
nameaddrmstr_1.city
END
ELSE 'Other'
END
SELECT #temp.city AS city,
MAX(#temp.ytdshipments) AS ytdshipments,
MAX(#temp.ytdtotalweight) AS ytdtotalweight,
MAX(#temp.ytdtotalcharges) AS ytdtotalcharges
FROM #temp WITH(nolock)
LEFT OUTER JOIN ##temp
ON ##temp.city = #temp.city
GROUP BY #temp.city
DROP TABLE #temp
DROP TABLE ##temp
My guess is that you're trying to squeeze a number greater than 99999.99 into your decimal fields. Changing it to (8,3) isn't going to do anything if it's greater than 99999.999 - you need to increase the number of digits before the decimal. You can do this by increasing the precision (which is the total number of digits before and after the decimal). You can leave the scale the same unless you need to alter how many decimal places to store. Try decimal(9,2) or decimal(10,2) or whatever.
You can test this by commenting out the insert #temp and see what numbers the select statement is giving you and see if they are bigger than your column can handle.
I feel I need to clarify one very important thing, for others (like my co-worker) who came across this thread and got the wrong information.
The answer given ("Try decimal(9,2) or decimal(10,2) or whatever.") is correct, but the reason ("increase the number of digits before the decimal") is wrong.
decimal(p,s) and numeric(p,s) both specify a Precision and a Scale. The "precision" is not the number of digits to the left of the decimal, but instead is the total precision of the number.
For example:
decimal(2,1) covers 0.0 to 9.9, because the precision is 2 digits (00 to 99) and the scale is 1.
decimal(4,1) covers 000.0 to 999.9
decimal(4,2) covers 00.00 to 99.99
decimal(4,3) covers 0.000 to 9.999
(7,2) it means, variable will contain 5 digits before the decimal and 2 digits after decimal .if you are putting 7 digits before the decimal that is wrong.
for better understand :- https://www.sqlshack.com/understanding-sql-decimal-data-type/
If you want to reduce the size to decimal(7,2) from decimal(9,2) you will have to account for the existing data with values greater to fit into decimal(7,2). Either you will have to delete those numbers are truncate it down to fit into your new size. If there was no data for the field you are trying to update it will do it automatically without issues
Use TRY_CAST function in exact same way of CAST function. TRY_CAST takes a string and tries to cast it to a data type specified after the AS keyword. If the conversion fails, TRY_CAST returns a NULL instead of failing.
I approach these problems by trying to isolate the select statement.
Comment out fields until you can isolate which field is actually the problem.
Once you can say : Select from
you can then add Cast(field as numeric(4,6)) [tryMe]
This has the benefit of selecting N rows and then throwing the error.
You can then take the cast off and see what value N+1 has.
The result is usually surprising... or you would not be reading this SO!
I had a problem today where I was calculating tax and had Numeric(7,4)
The issue wound up being I had one order that owed 1000$ in tax.
Numeric(7,4) will only allow 3 digits to the left of the decimal.
DOH!
check your value which you want to store in integer column. I think this is greater then range of integer. if you want to store value greater then integer range. you should use bigint datatype

SELECT SUM for time

I have a Table in SQL server with a column "Time" having data type as time(7). Need to call the sum of this column, and when I use the following statement, it returns result as integer only.
Eg. If total time is 1:30:00,I expect result as 1.5. But the code I use doesn't get me this, it get me result as 1. Please check if you have a solution.
The code I used is
SELECT SUM(DATEPART(ss,Time) + DATEPART(mi,Time)*60 + DATEPART(hh,Time)*3600)/3600 AS TotalTime FROM dbo.Table
SELECT (
DATEPART(hh,Time) +
DATEPART(mi,Time) / 60.0 +
DATEPART(ss,Time) / 3600.0
) AS TotalTime
FROM dbo.Table
Try below - you don't need sum() function here and in your case, it is showing 1 because your result is 5400/3600 which is 1 but you need to add a float value as you are expecting float result
SELECT (DATEPART(ss,'1:30:00') + DATEPART(mi,'1:30:00')*60 +
DATEPART(hh,'1:30:00')*3600)/3600.00
AS TotalTime FROM dbo.Table
Try this, you can change the datepart argument based on your needs here is the full list
SELECT SUM(CAST(DATEDIFF(MINUTE, '00:00:00', [Time]) as float)/60) AS TotalHours FROM [dbo].[Table]
When you divide some value by int type, the result will be also int (the fraction is just dropped). Therefore, you need to convert a divider of 3600 from int to decimal:
SELECT SUM(DATEPART(ss,Time) + DATEPART(mi,Time)*60 + DATEPART(hh,Time)*3600)/CONVERT(DECIMAL(16,4), 3600) AS TotalTime FROM dbo.Table
If you want the difference in decimal hours, then do the following:
Convert the time values to seconds.
Sum the seconds.
Divide by 60 * 60
So:
select sum(datediff(second, 0, v.t)) / (60.0 * 60)
from (values (convert(time, '00:10:01')),
(convert(time, '01:00:03'))
) v(t)
There is no reason to break the value in to component parts. That just seems unnecessarily complicated.

How do I convert a 5 or 6 digit decimal to a date in sql

I've got a column that shows the date as a decimal such as 101118 for 10-11-18 and 90118 for 09-01-18. I am trying to create a simple report that would give me all reservations yesterday.
So for example
Select playerid, datereservationmade
from dbo.lms
normally there is very simple and I would just do
Select playerid, datereservationmade
from dbo.lms
where datereservationmade >= dateadd(day,datediff(day,1,GETDATE()),0)
AND datereservationmade < dateadd(day,datediff(day,0,GETDATE()),0)
That does not work in this case because the datereservationmade field is a decimal and if its a month 1-9 it leaves off the 0 and makes it a 5 digit decimal then if its 10-12 it is a 6 digit decimal.
Someone please help me figure out how to convert this!
If at all possible, you really should fix your schema so that dates are actually being stored as dates.
If you need to work with the decimal data type, you can use something like the following...
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
BEGIN DROP TABLE #TestData; END;
CREATE TABLE #TestData (
decimal_date DECIMAL(6, 0) NOT NULL
);
INSERT #TestData (decimal_date) VALUES (101118), (90118), (101718);
--==============================================
SELECT
td.decimal_date,
dd.date_date
FROM
#TestData td
CROSS APPLY ( VALUES (RIGHT('0' + CONVERT(VARCHAR(6), td.decimal_date), 6)) ) cd (char_date)
CROSS APPLY ( VALUES (CONVERT(DATE, STUFF(STUFF(cd.char_date, 5, 0, '/'), 3, 0, '/'), 1)) ) dd (date_date)
WHERE
dd.date_date = CONVERT(DATE, DATEADD(DAY, -1, GETDATE()));
Convert the decimal to varchar(6) by adding a zero in front and getting the RIGHT 6 characters.
Then convert the string to a date from its parts, which are substrings in your varchar(6). This is made easier in SQL Server 2012 with the DATEFROMPARTS function.
Using the DATEFROMPARTS, as Tab Alleman suggested, you might get something like this:
-- Example of the arithmetic
SELECT 101118 / 10000 AS Month, (101118 % 10000) / 100 AS Day, (101118 % 100) AS Year
-- Using the math in DATEFROMPARTS
SELECT DATEFROMPARTS((101118 % 100) + 2000, 101118 / 10000, (101118 % 10000) / 100 )
However, I'm skeptical that you've provided all the correct information. What happens on January first? Your decimal value won't start with zero (as you stated). Will your day always pad with zero? If not, then 1119 won't produce the same result as 10119. If, however, your day does start with zero, then the equation above should work fine.

how to get rid off decimals from sql results

I am calculating total hours/minutes but i would like to get rid off the decimals and only show something like this 2.00 hours or 2.5 hours etc. I am getting now something like this: 2.000000 and want only to limit to 2 decimals only.
select DATEDIFF(minute, Min(FullDatetime), Max(FullDatetime)) / 60.0 as hours
from myTable
where userid = 123
You can do it by rounding but the easiest is to format for output using FORMAT().
select FORMAT(DATEDIFF(minute, Min(FullDatetime), Max(FullDatetime)) / 60.0, 'N2') as hours
from myTable
where userid = 123
Helpful original documentation: here
try use
cast('values' as decimal(18,2)) --2 decimal place.
select Cast((DATEDIFF(minute, Min(FullDatetime), Max(FullDatetime)) / 60.0 as hours)as decimal(18,2))
from myTable
where userid = 123
There are a few options out there.
I prefer to use the following when no rounding is needed
FORMAT(value, 'N2')
SQL - Rounding off to 2 decimal places
how to get 2 digits after decimal point in tsql?
just use ROUND function such as : SELECT ROUND(columnName,decimals) from table
You could use STR or CONVERT function:
DECLARE #v NUMERIC(19, 6)
SET #v = 2.189189
SELECT STR(#v, 19, 2) AS Method1_Result_VARCHAR, CONVERT(NUMERIC(15, 2), #v) AS Method2_Result_NUMERIC
/*
Method1_Result_VARCHAR Method2_Result_NUMERIC
---------------------- ----------------------
2.19 2.19
*/
Note: First argument of STR function has float type and this means that 1) SQL Server will convert this argument from numeric to float and 2) method 1 uses a non-deterministic expression.

convert varchar(8) values and use ASC in T-SQL

I have a data in the table in the form below and it is in varchar(8) datatype
Total
100
101
104.5
88
1038
64
108.3
10872
900
I like to use ASC in T-sql so that I can display it into ascending order, however I
cannot do it as it is in varchar(8) form
For example
select Total from
Table A
Order by Total ASC
How to first add these values into Temporary temp table?
and How to convert this varchar(8) values and into what? so that
you can display them in ASC or ascending order using T-SQL query?
Anyone?
You could cast the value like this.
SELECT
Total
FROM Table A
ORDER BY CAST(Total AS FLOAT) ASC
You may lose data converting back to float.
So here is a varchar based sort.
DECLARE #badDesign TABLE (floatcol varchar(8) NOT NULL);
INSERT #badDesign VALUES ('100'),('101'),('104.5'),('88'),('1038'),('64'),('108.3'),('10872'),('900'),('108'), ('108.32'), ('108.4')
SELECT *
FROM #badDesign
ORDER BY
RIGHT('00000000' +
CASE
WHEN CHARINDEX('.', floatcol) = 0 THEN floatcol
ELSE LEFT(floatcol, CHARINDEX('.', floatcol)-1)
END
, 8),
CASE
WHEN CHARINDEX('.', floatcol) = 0 THEN '.0'
ELSE SUBSTRING(floatcol, CHARINDEX('.', floatcol)+1, 8)
END
The values from your example looks like float numbers. So
1) Since they all have no more than 8 digits, you can cast it to float(53) (it has about 15 decimal digits precision) without loss of data. Or to decimal(15,7) to be completely sure.
2) Generally it's strange to store float values as strings in the database.
Use CAST or CONVERT functions, e.g.:
select Total from
Table A
Order by CAST(Total as float) ASC
Reference: http://msdn.microsoft.com/en-us/library/ms187928.aspx
Unless you want to keep the converted values, you don't need to store it in a temporary table. Just convert them for the sorting:
select Total
from [Table A]
order by cast(Total as float)
(Ascending is the default way to sort, so you don't have to specify that.)