Trouble converting from time to decimal time - sql

Part of the task I have been given involves performing calculations on a few columns, 2 of which are in the format of hh.mi.ss and they're varchar. In order for the calculations to work, I need to get them into a time decimal format, whereby 1:30 would be 1.5 . Since I'm currently using SQL Server 2005, I don't have the time or data types built-in and I'm unable to get an upgraded version (not my choice). Working with what I have, I've searched around online and tried to convert it but the result isn't accurate. For example, 13.28 becomes (roughly) 13.5, which is great, however, the seconds go to 100 instead of ending at 60 (since I'm converting it to a float).
For example, using 12.57.46,
CAST(DATEPART(HH, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME)) AS FLOAT) +
(CAST(DATEPART(MI, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME)) AS FLOAT)/60) +
(CAST(DATEPART(SS, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME)) AS FLOAT)/3600)
gave me 12.962...
whereas
CAST(SUBSTRING([OASTIM], 1, 2) AS FLOAT) +
((CAST(SUBSTRING([OASTIM], 4, 5) AS FLOAT) +
CAST(SUBSTRING([OASTIM], 7, 8) AS FLOAT)/60)/60)
gave me 12.970....
and when I tried something simpler,
DATEPART(HOUR, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME))+
(DATEPART(MINUTE, CAST(REPLACE([OASTIM], '.', ':') AS DATETIME))/60)
flopped out and gave me only 12
It's my first exposure to Windows SQL and T-SQL, I've been struggling with this for a few hours. As horrible as it sounds, I'm at the point where I'd be happy with it working even it it means sacrificing performance.

You don't explain what "time decimal" format is. From your example, I'll guess that you mean decimal hours.
A key function in SQL Server for date differences is datediff(). You can convert the time to seconds using a trick. Add the time to a date, then use datediff() to get the number of seconds after midnight. After that, the conversion to decimal hours is just arithmetic.
Here is an example:
select datediff(second,
cast('2000-01-01' as datetime),
cast('2000-01-01 ' + '00:00:59' as datetime)
)/3600.0 as DecimalHours
Note the use of the constant 3600.0. The decimal point is quite important, because SQL Server does integer division on integer inputs. So, 1/2 is 0, rather than 0.5.

You said,
CAST(SUBSTRING([OASTIM], 1, 2) AS FLOAT) +
((CAST(SUBSTRING([OASTIM], 4, 5) AS FLOAT) +
CAST(SUBSTRING([OASTIM], 7, 8) AS FLOAT)/60)/60)
gave me 12.970....
12.970 is wrong for an input of '12.57.46'. The problem is that you are using the SUBSTRING function incorrectly. The 3rd argument represents the number of characters, not the ending character position.
Take a look at this code:
Declare #Sample varchar(20)
Set #Sample = '12.57.46'
select CAST(SUBSTRING(#Sample, 1, 2) AS FLOAT) +
CAST(SUBSTRING(#Sample, 4, 5) AS FLOAT) / 60 +
CAST(SUBSTRING(#Sample, 7, 8) AS FLOAT) / 60 / 60,
SUBSTRING(#Sample, 1, 2),
SUBSTRING(#Sample, 4, 5),
SUBSTRING(#Sample, 7, 8),
CAST(SUBSTRING(#Sample, 1, 2) AS FLOAT) +
CAST(SUBSTRING(#Sample, 4, 2) AS FLOAT) / 60 +
CAST(SUBSTRING(#Sample, 7, 2) AS FLOAT) / 60 / 60
Notice that the minutes is coming out as 57.46 because you are asking for 5 characters. The seconds are coming out correctly because eventhough you are asking for 8 characters, there are only 2 characters left in the string so only those 2 characters are returned.
BTW, I would solve this problem the same way that Gordon did, except I would remove the date stuff so it would look like this:
Select DateDiff(Second,
0,
Convert(DateTime, Replace([OASTIM], '.',':'))) / 3600.0

Here is a simple way to convert time to DecimalHours.
SELECT cast(cast('12.57:46' as datetime) as float) * 24
Result:
~12.963

Related

Change nonth from 8 to 08 in SQL query

I am trying to get the month year from date that is in database.
I used the following query to get the date. But the formatting is not as I require. Due to this my query is not giving the result which I am expecting.
select top 3 datepart(yyyy, cia.DateCreated) as YYyy, datepart(mm, cia.DateCreated) as mm,
case when (datepart(mm, cia.DateCreated) < 10) then
cast(concat('0',datepart(mm, cia.DateCreated)) as varchar)
else
datepart(mm, cia.DateCreated)
end as Months
from v_AuthListInfo cia
I am getting the month values as 1, 2, 3, 4, 5, 6, 7, 8 but I need the value like 01, 02, 03, 04 ...
I tried to use DatePart, Cast and Concatinate function but still I am getting the data like 1, 2, 3, 4.
use right() function
RIGHT('0' + RTRIM(MONTH(cia.DateCreated)), 2);
You can use the built-in function format():
format(month(cia.DateCreated), '00')
If you want to use the right() method, I would suggest:
right(concat('00', month(cia.DateCreated)), 2)
Here's general approach how to pad with ceratin character:
right(#padding + cast(#stringToPad as varchar), 2)
where #padding consists of characters you want to use and its length has to be the desired length, so in your case it would be 00.
#stringToPad is string you want to extend, in your case cast(month(cia.DateCreated) as varchar).
So finally, giving an example, it would look like:
select right('00' + cast(1 as varchar), 2)

SQL Convert Military time to Time

I have a sql database where clock in times are displayed as military time, but in number format. E.g. 907 is 09:07am, or 1514 is 15:14pm
Is there any way of converting this in SQL?
Currently I output into excel and use the below formula to calculate but would prefer to do all this in SQL
TIMEVALUE(LEFT(IF(LEN(L30)=4,L30,CONCATENATE(0,L30)),2)&":"&MID(IF(LEN(L30)=4,L30,CONCATENATE(0,L30)),3,2)&":"&RIGHT(IF(LEN(L30)=4,L30,CONCATENATE(0,L30)),2))
Any help you be appropriated
Thanks
If you want the output as a time value:
select convert(time, dateadd(second, t/100 * 60 + t % 100, 0))
from (values (907), (1514)) v(t);
If you just want a string returned:
select stuff(right('0' + convert(varchar(255), t), 4), 3, 0, ':')
from (values (907), (1514)) v(t);

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.

Convert string formatted as yyyymmddhhnn to datetime

I have a table in an SQL Server database with a date field in it, presented as varchar in yyyymmddhhnn format (where nn is minutes). For example, 200012011200 would be 01 Dec 2000 12:00. I need to convert this to a datetime value, but none of the convert codes seems to cover it. It's closest to ISO format yyyymmdd but that doesn't include the time part, so calling convert(datetime, MyDateField, 112) fails.
The time part is important, so I can't just strip it off. How can I convert this to datetime?
Try this
declare #t varchar(20)
set #t='200012011200'
select cast(stuff(stuff(#t, 11,0,':'),9,0,' ') as datetime)
SELECT convert(varchar, cast(SUBSTRING('200012011200',1,4)+
'-'+SUBSTRING('200012011200',5,2)+
'-'+SUBSTRING('200012011200',7,2)+
' '+SUBSTRING('200012011200',9,2)+
':'+SUBSTRING('200012011200',11,2)+
':00'+
'.000' AS DATETIME), 109)
This will result in Dec 1 2000 12:00:00:000PM
Using the 112 as parameter will result to 20001201
Enjoy
UPDATE:
The convert(varchar...) is just for demonstration purposes.
You can use this as well:
SELECT CAST(SUBSTRING('200012011200',1,4)+
'-'+SUBSTRING('200012011200',5,2)+
'-'+SUBSTRING('200012011200',7,2)+
' '+SUBSTRING('200012011200',9,2)+
':'+SUBSTRING('200012011200',11,2)+
':00'+
'.000' AS DATETIME)
My own rather brute-forced solution:
dateadd(mi, cast(substring(MyDateTime, 11, 2) as int), dateadd(hh, cast(substring(MyDateTime, 9, 2) as int), convert(datetime, left(MyDateTime, 8), 112)))
A horrendous contraption, but it does the job. Broken down from inside to out:
convert(datetime, left(MyDateTime, 8), 112)
Get the first 8 characters (yyyymmdd) and convert as ISO format.
dateadd(hh, cast(substring(MyDateTime, 9, 2) as int), ...)
Add on the hours with dateadd - characters 9 and 10, but needs to be cast and int before use in dateadd.
dateadd(mi, cast(substring(MyDateTime, 11, 2) as int), ...)
Add on the minutes with the same method, characters 11 and 12.
I can't imagine this solution could be any uglier without intentionally obfuscating it, and I doubt it's terribly efficient, but it does work.

SQL rounding to a 2 decimals [duplicate]

I need to convert minutes to hours, rounded off to two decimal places. I also need to display only up to two numbers after the decimal point. So if I have minutes as 650, then hours should be 10.83.
Here's what I have so far:
Select round(Minutes/60.0,2) from ....
But in this case, if my minutes is, say, 630 - hours is 10.5000000. But I want it as 10.50 only (after rounding). How do I achieve this?
You could cast your result as numeric(x,2). Where x <= 38.
select
round(630/60.0,2),
cast(round(630/60.0,2) as numeric(36,2))
Returns
10.500000 10.50
With SQL Server 2012, you can use the built-in format function:
SELECT FORMAT(Minutes/60.0, 'N2')
You can use:
select cast((630/60.0) as decimal(16,2))
in SQL Server
Declare #number float = 35.44987665;
Select round(#number,2)
CAST(QuantityLevel AS NUMERIC(18,2))
Convert your number to a Numeric or Decimal.
Replace your query with the following.
SQL Server
Select Convert(Numeric(38, 2), Minutes/60.0) from ....
MySQL:
Select Convert(Minutes/60.0, Decimal(65, 2)) from ....
The Cast function is a wrapper for the Convert function. Couple that with SQL being an interpreted language and the result is that even though the two functions produce the same results, there is slightly more going on behind the scenes in the Cast function.
Using the Convert function is a small saving, but small savings multiply. The parameters for Numeric and Decimal (38, 2) and (65, 2) represent the maximum precision level and decimal places to use.
DECLARE #porcentaje FLOAT
SET #porcentaje = (CONVERT(DECIMAL,ABS(8700)) * 100) / CONVERT(DECIMAL,ABS(37020))
SELECT #porcentaje
Try this:
SELECT CAST(ROUND([Amount 1]/60,2) AS DECIMAL(10,2)) as TOTAL
Following query is useful and simple-
declare #floatExchRate float;
set #floatExchRate=(select convert(decimal(10, 2), 0.2548712))
select #floatExchRate
Gives output as 0.25.
This works in both with PostgreSQL and Oracle:
SELECT ename, sal, round(((sal * .15 + comm) /12),2)
FROM emp where job = 'SALESMAN'
Whatever you use in denomination should be in decimal. For example, 1548/100 will give 15.00.
If we replace 100 with 100.0 in our example then we will get 15.48
select 1548/100
15.00000
select 1548/100.0
15.4800
0
As an add-on to the answers below, when using INT or non-decimal datatypes in your formulas, remember to multiply the value by 1 and the number of decimals you prefer.
I.e. - TotalPackages is an INT, and so is the denominator TotalContainers, but I want my result to have up to six decimal places.
Thus:
((m.TotalPackages * 1.000000) / m.TotalContainers) AS Packages,
The following snippet might help you:
select SUBSTR(ENDDTTM,1, 9), extract(DAY FROM (ENDDTTM)), ENDDTTM, BEGINDTTM, (ENDDTTM - BEGINDTTM),substr(BEGINDTTM, 1,15), substr((ENDDTTM - BEGINDTTM), 12, 8),
round((substr((ENDDTTM - BEGINDTTM), 12, 2)* 3600 + substr((ENDDTTM - BEGINDTTM), 15, 2)*60 + substr((ENDDTTM - BEGINDTTM), 18, 2)),2) as seconds,
round((substr((ENDDTTM - BEGINDTTM), 12, 2)* 60 + substr((ENDDTTM - BEGINDTTM), 15, 2) + substr((ENDDTTM - BEGINDTTM), 18, 2)/60 ), 2)as minutes,
round((substr((ENDDTTM - BEGINDTTM), 12, 2) + substr((ENDDTTM - BEGINDTTM), 15, 2)/60 + substr((ENDDTTM - BEGINDTTM), 18, 2)/3600 ),2) as hours
I find the STR function the cleanest means of accomplishing this.
SELECT STR(ceiling(123.415432875), 6, 2)
To round up to x decimal places:
SET #Result = CEILING(#Value * POWER(10, #Decimals)) / POWER(10, #Decimals)
where #Value is the value of the item to be rounded, #Decimals is the number of decimal places, for example, two in this instance.
This worked for me:
SELECT FORMAT(Minutes/60.0, '0.00')