Left-filling a text field with zeros - sql

I have a postgres database that I can access with PGAdmin III. I run a script to change a number stored in a text field and then add left zeros to file it to four characters. It's a time field that must be stored as text. I'd like to do it in a single run instead of two. Here's the first clause to add hours to the time field as text;
UPDATE timetable
SET eta = (
CASE
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) < 24 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 )) * 100
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) > 23 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 ) - 24) * 100
END )
FROM
destination,
trips
WHERE
timetable.tripsid = trips.id;
This does fine and adds the desired number of hours while correcting for results of greater than 24 hours. However, this leave any times less than 1000 hours as three digits or even a single 0 for midnight. The field needs to be 4 characters.
So I run this as a second clause;
UPDATE timetable
SET eta = lpad(eta, 4, '0');
and this works also. But how can I add the lpad to the first Update clause? I tried putting the entire CASE statement in the lpad statement in place of eta like this;
SET eta = lpad((CASE statement here), 4, '0')
but I get this error;
ERROR: function lpad(numeric, integer, unknown) does not exist
LINE 3: SET eta = lpad((
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
I've tried casting eta with ::int, ::text, and ::varchar, but that just return a sytax error.

should be LPAD(your_col::text, 4, '0')
UPDATE timetable
SET eta = LPAD ((
CASE
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) < 24 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 )) * 100
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) > 23 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 ) - 24) * 100
END )::text, 4,'0')
FROM destination
INNER JOIN trips ON timetable.tripsid = trips.id;

Why are you using LPAD if the result of your CASE statement is numeric , use simply to_char :
UPDATE timetable
SET eta = to_char (
CASE
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) < 24 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 )) * 100
WHEN (trips.starttime::int / 100) + (destination.zuluoffset * -1 ) > 23 THEN ((trips.starttime::int / 100) + (destination.zuluoffset * -1 ) - 24) * 100
END , 'FM0000')
FROM destination
INNER JOIN trips ON timetable.tripsid = trips.id;

Related

SQL Convert Milliseconds to Days, Hours, Minutes

I need convert a millisecond value, 85605304.3587 to a value like 0d 18h 21m.
No idea on how to start that, is there something similar to a TimeSpan in SQL like there is in C#?
You can do the calculation explicitly. I think it is:
select floor(msvalue / (1000 * 60 * 60 * 24)) as days,
floor(msvalue / (1000 * 60 * 60)) % 24 as hours,
floor(msvalue / (1000 * 60)) % 60 as minutes
Note: Some databases use mod instead of %.
In MS SQL SERVER you can use next code:
with cte as (
select cast(85605304.3587 as int) / 1000 / 60 as [min]
), cte2 as (
select
cast([min] % 60 as varchar(max)) as minutes,
cast(([min] / 60) % 24 as varchar(max)) as hours,
cast([min] / (60 * 24) as varchar(max)) as days
from cte
)
select concat(days, 'd ', hours, 'h ', minutes, 'm') as tm
from cte2
Using native date & time functions, maybe:
SELECT
AsDateTime = DATEADD(MILLISECOND, 85605304, 0)
, AsDateTime2 = DATEADD(NANOSECOND, 7 * 100, DATEADD(MICROSECOND, 358, DATEADD(MILLISECOND, 85605304, CONVERT(datetime2, CONVERT(datetime, 0)))))
-- Incorrect datetime2 approach I initially did, has some precision loss, probably due to datetime's millisecond issue with 0's, 3's, and 7.'s
--SELECT DontDoThis = DATEADD(NANOSECOND, 7 * 100, DATEADD(MICROSECOND, 358, CONVERT(datetime2, DATEADD(MILLISECOND, 85605304, 0))))
datetime covers only 3 digits beyond seconds, while datetime2 will maintain 7 digits. Perhaps other ways that give date-like objects exist, I wouldn't know.

Is there any way I can convert VARCHAR2 to SECONDS?

My output is like this
**Column1** **Column2**
20170123012057.555 20170123070616.314
I should get 20719 seconds if I minus the two columns
You can convert the values to a date and then take the difference:
select (to_date(substr(column2, 1, 14), 'YYYYMMDDHH24MISS') -
to_date(substr(column1, 1, 14), 'YYYYMMDDHH24MISS')
) * 24 * 60 * 60
Try this. Here I have given difference in milliseconds as well as in seconds which is rounded
select
extract(day from (to_timestamp(column2,'YYYYMMDDHH24MISS.FF')
-to_timestamp(column1,'YYYYMMDDHH24MISS.FF')
)*86400*1000) / 1000
as diff_in_milliseconds
,round(extract(day from (to_timestamp(column2,'YYYYMMDDHH24MISS.FF')-
to_timestamp(column1,'YYYYMMDDHH24MISS.FF')
)*86400*1000) / 1000
) as diff_in_seconds
from
(select
'20170123012057.555' as Column1,
'20170123070616.314' as Column2
from dual)
Output
DIFF_IN_MILLISECONDS DIFF_IN_SECONDS
20718,7590 20719
Try as
SELECT ROUND (seconds / 1000) seconds
FROM (SELECT EXTRACT (DAY FROM cal_col) * 24 * 60 * 60 * 1000
+ EXTRACT (HOUR FROM cal_col) * 60 * 60 * 1000
+ EXTRACT (MINUTE FROM cal_col) * 60 * 1000
+ ROUND (EXTRACT (SECOND FROM cal_col) * 1000)
seconds
FROM (SELECT TO_TIMESTAMP ('20170123070616.314',
'YYYYMMDDHH24MISS.FF')
- TO_TIMESTAMP ('20170123012057.555',
'YYYYMMDDHH24MISS.FF')
cal_col
FROM DUAL))

Incorrect syntax near the keyword 'FROM' in my query

SELECT dbo.ScrCalcr$.AgingDays, dbo.ScrCalcr$.EndingCount, dbo.ScrCalcr$.Priority, dbo.ScrCalcr$.TPDUNS, Score=(
CASE
WHEN dbo.ScrCalcr$.AgingDays >= 150 THEN
CASE
WHEN dbo.ScrCalcr$.EndingCount >= 150 THEN
((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 1
ELSE((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 0.1
END
ELSE 0
END
FROM dbo.ScrCalcr$
ORDER BY Score DESC
GO
I am getting an error as:
Msg 156, Level 15, State 1, Line 12
Incorrect syntax near the keyword 'FROM'.
I'm missing the right paranthesis of: Score=(.
So this should work:
SELECT dbo.ScrCalcr$.Agingdays,
dbo.ScrCalcr$.Endingcount,
dbo.ScrCalcr$.Priority,
dbo.ScrCalcr$.Tpduns,
Score=( CASE
WHEN dbo.ScrCalcr$.Agingdays >= 150 THEN
CASE
WHEN dbo.ScrCalcr$.Endingcount >= 150 THEN
(
( 10 * dbo.ScrCalcr$.Endingcount ) + ( 15 *
dbo.ScrCalcr$.Agingdays ) ) /
(
dbo.ScrCalcr$.Priority * 0.1
)
* 1
ELSE( ( 10 * dbo.ScrCalcr$.Endingcount ) +
( 15 * dbo.ScrCalcr$.Agingdays ) ) / (
dbo.ScrCalcr$.Priority * 0.1 ) * 0.1
END
ELSE 0
END )
FROM dbo.ScrCalcr$
ORDER BY Score DESC
We don't have your data model, so I can't say for certain, but it seems you need something like this:
SELECT dbo.ScrCalcr$.AgingDays, dbo.ScrCalcr$.EndingCount, dbo.ScrCalcr$.Priority, dbo.ScrCalcr$.TPDUNS
FROM dbo.ScrCalcr$
WHERE Score=(
CASE
WHEN dbo.ScrCalcr$.AgingDays >= 150 THEN
CASE
WHEN dbo.ScrCalcr$.EndingCount >= 150 THEN
((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 1
ELSE((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 0.1
END
ELSE 0
END )
ORDER BY Score DESC
I moved the condition to the where clause and removed the line break. Also, added a ) after END.
If you meant Score to be a field in your result, use this:
SELECT dbo.ScrCalcr$.AgingDays, dbo.ScrCalcr$.EndingCount, dbo.ScrCalcr$.Priority, dbo.ScrCalcr$.TPDUNS
, CASE
WHEN dbo.ScrCalcr$.AgingDays >= 150 THEN
CASE
WHEN dbo.ScrCalcr$.EndingCount >= 150 THEN
((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 1
ELSE((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 0.1
END
ELSE 0
END
Score
FROM dbo.ScrCalcr$
ORDER BY Score DESC
SELECT S.AgingDays,
S.EndingCount,
S.Priority,
S.TPDUNS,
CASE WHEN S.AgingDays >= 150 THEN (
CASE WHEN S.EndingCount >= 150 THEN ((10 * S.EndingCount) + (15 * S.AgingDays))/ (S.Priority * 0.1) * 1
ELSE((10 * S.EndingCount) + (15 * S.AgingDays))/ (S.Priority * 0.1) * 0.1
END)
ELSE 0 END Score
FROM dbo.ScrCalcr$ S
ORDER BY Score DESC
GO
You Give ) parenthesis After END Statement
like this
SELECT dbo.ScrCalcr$.AgingDays,
dbo.ScrCalcr$.EndingCount
, dbo.ScrCalcr$.Priority,
dbo.ScrCalcr$.TPDUNS,
Score=
(
CASE
WHEN dbo.ScrCalcr$.AgingDays >= 150 THEN
CASE
WHEN dbo.ScrCalcr$.EndingCount >= 150 THEN
((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 1
ELSE((10 * dbo.ScrCalcr$.EndingCount) + (15 * dbo.ScrCalcr$.AgingDays))/ (dbo.ScrCalcr$.Priority * 0.1) * 0.1
END
ELSE 0
END)
FROM dbo.ScrCalcr$
ORDER BY Score DESC
GO

convert decimal to HH.MM format in SQl Server

How to convert decimal to HH.MM format in SQl Server. Example:- 06.85 will be converted to 07.25, 06.60 will be converted to 7.00
SELECT
CASE
WHEN DecimalValue - FLOOR(DecimalValue) >= 0.6 THEN DecimalValue + 1 - 0.6
ELSE DecimalValue
END AS HHMMFormat
FROM
MyTable
Obviously the + 1 - 0.6 could be replaced by + 0.4 but I thought that + 1 - 0.6 more clearly showed the reason for the addition.
select floor(06.85) + cast(((06.85 - floor(06.85))*100) as int) / 60 + cast((cast((06.85 - floor(06.85)) * 100 as int) % 60) as float) / 100
select floor(06.60) + cast(((06.60 - floor(06.60))*100) as int) / 60 + cast((cast((06.60 - floor(06.60)) * 100 as int) % 60) as float) / 100

Convert Military time to string representation

I have an column declared as int (called HourMil) which stores the time in military format. I need to convert this values to an formatted string (HH:MM)
example
HourMil = 710 -> must be 07:10
HourMil = 1305 -> must be 13:05
Actually I am using this code (and works ok) for convert the column HourMil to the string representation.
SELECT SUBSTRING(LEFT('0',4-LEN(CAST(HourMil AS VARCHAR)))+CAST(HourMil AS VARCHAR),1,2)+':'+SUBSTRING(LEFT('0',4-LEN(CAST(HourMil AS VARCHAR)))+CAST(HourMil AS VARCHAR),3,2) FROM MYTABLE
but I think this code can be improved.
By creating a date, then formatting it:
SELECT SUBSTRING(CONVERT(nvarchar, DATEADD
(hh, HourMil / 100, DATEADD(mi, HourMil % 100, '1900-01-01')), 8), 0, 6)
Equations:
H = HourMil / 100;
M = HourMil - ( HourMil / 100 ) * 100;
Examples of working:
H = 710 / 100 = 7
M = 710 - (710 / 100) * 100 = 10
H = 1305 / 100 = 13
M = 1305 - (1305 / 100) * 100 = 5
Note: All /* operators MUST working under decimal numbers only. (integers)
Then you SQL will be:
CONCAT(CAST(H AS VARCHAR(8)), ':', CAST(M AS VARCHAR(8)));
With equations final seems to be:
CONCAT(CAST((HourMil / 100) AS VARCHAR(8)), ':', CAST((HourMil - ( HourMil / 100 ) * 100) AS VARCHAR(8)));
This is another method and also a shortest one
select stuff(right('0'+ltrim(hourmail),4),3,0,':') from
(
select 710 as hourmail union all
select 1305
) as t