Two questions for formatting timestamp and number using postgresql - sql

I am selecting a date column which is in the format "YYYY-MM-DD".
I want to cast it to a timestamp such that it will be "YYYY-MM-DD HH:MM:SS:MS"
I attempted:
select CAST(mycolumn as timestamp) from mytable;
but this resulted in the format YYYY-MM-DD HH:MM:SS
I also tried
select TO_TIMESTAMP(mycolumn,YYYY-MM-DD HH:MM:SS:MS) from mytable;
but this did not work either. I cannot seem to figure out the correct way to format this. Note that I only want the first digit of the milliseconds.
//////////////second question
I am also trying to select numeric data such that there will not be any trailing zeros.
For example, if I have values in a table such as 1, 2.00, 3.34, 4.50.
I want to be able to select those values as 1, 2, 3.34, 4.5.
I tried using ::float, but I occasionally strange output. I also tried the rounding function, but how could I use it properly without knowing how many decimal points I need before hand?
thanks for your help!

It seems that the functions to_timestamp() and to_char() are unfortunately not perfect.
If you cannot find anything better, use these workarounds:
with example_data(d) as (
values ('2016-02-02')
)
select d, d::timestamp || '.0' tstamp
from example_data;
d | tstamp
------------+-----------------------
2016-02-02 | 2016-02-02 00:00:00.0
(1 row)
create function my_to_char(numeric)
returns text language sql as $$
select case
when strpos($1::text, '.') = 0 then $1::text
else rtrim($1::text, '.0')
end
$$;
with example_data(n) as (
values (100), (2.00), (3.34), (4.50))
select n::text, my_to_char(n)
from example_data;
n | my_to_char
------+------------
100 | 100
2.00 | 2
3.34 | 3.34
4.50 | 4.5
(4 rows)
See also: How to remove the dot in to_char if the number is an integer

SELECT to_char(current_timestamp, 'YYYY-MM-DD HH:MI:SS:MS');
prints
2016-02-05 03:21:18:346

just add ::timestamp without time zone
select mycolumn::timestamp without time zone from mytable;

Related

Snowflake converting numeric value into HHMMSS format

I have a column that has number in it in the format of HHMMSS but the number is not consistent (not all have six digits), ex: "83455" "153651" "91251".
The number 83455 would mean 8:34 am and 55 as SS. I tried converting into varchar and use TO_TIME but the output is not the same as it is. Similarly, I also tried converting into timestamp then get the time from it but it just won't work. The output I want here would be 8:34:55, what is the best way to convert the number?
Try this. I split hours minutes and seconds and then concatenate them into time format.
SELECT
CAST(FLOOR(col / 10000) || ':' ||
FLOOR(MOD(col / 100, 100)) || ':' ||
MOD(col, 100) AS TIME) AS converted_time
FROM
yourtable
MOD()
An alternative approach is to use the built in function for this task.
TRY_TO_TIME().
Sometimes the built in functions are easier to read, understand, less typing, optimized (runs faster/cheaper).
SELECT
TRY_TO_TIME (DONT_WASTE, 'HH24MISS" )VOLIA
,TO_CHAR (VOLIA, 'HH12:MI:SS AM' ) AM_PM
FROM
(SELECT '83455 'DONT_WASTE UNION SELECT '153651 'UNION SELECT '91251')
The core of this problem is the format string was wrong
MM is Month, MI is minutes.
The first path I went down was slicing the string up, but the TO_TIME/TRY_TO_TIME both handle the smaller string of the pre lunchtime, but does not handle no hours, for that you might need to pad if you have such truncated values from number I assume:
select column1
,try_to_time(column1, 'HH24MMSS') as wrong
,try_to_time(column1, 'HH24MISS') as r1
,lpad(column1, 6, '0') as p
,try_to_time(p, 'HH24MISS') as r2
from values
('83455'),
('153651'),
('91251'),
('1251')
;
COLUMN1
WRONG
R1
P
R2
83455
null
08:34:55
083455
08:34:55
153651
null
15:36:51
153651
15:36:51
91251
09:00:51
09:12:51
091251
09:12:51
1251
12:00:01
null
001251
00:12:51
Thus inline it would be:
try_to_time(lpad(column1, 6, '0'), 'HH24MISS')

Remove Decimal but Keep Values - SQL

I have a data request - SQL Server 2014 (fourth column). The application does not handle decimals. So I have to provide the data without the decimals. For example: If an employee worked 8 hours, I am sending 8.00. The upstream application wants the data as 800. Or if its less than 8 hours then 050 (.50) for half hour.
My calculation for two weeks of work is:
CONVERT(decimal(10, 2), dur) / 60 AS HOURS
My question is: how do I strip that decimal yet maintain the correct hours such that 8.00 becomes 800?
You could simply convert the hours to a string and then replace the decimal with nothing. If necessary, convert the string without the decimal to an integer.
DECLARE #Hours DECIMAL(10, 2)
SET #Hours = 8.50
SELECT
#Hours AS [Hours]
, REPLACE(CONVERT(VARCHAR(13), #Hours), '.', '') AS [Hours as String]
, CONVERT(INT, REPLACE(CONVERT(VARCHAR(13), #Hours), '.', '')) AS [Hours as Integer]
Since your application is expecting leading zeros on values under an hour, you're going to have to pad that out. However, since there can be values over 10 hours, we need to treat those a little differently to account for the extra characters in the end result.
This seems to give the values you're looking for.
Setup:
create table t
(tm decimal(18,5));
insert t values (8.05999),(11.00000),(0.34111);
Query:
select
case
when t.tm > 10
then cast(cast(t.tm*100 as integer) as varchar(5)) --<-Handles longer shifts
else right(concat('000',cast(t.tm*100 as integer)),3) --<-Handles shorter shifts
end as appVal
from t;
Results:
+--------+
| appVal |
+--------+
| 805 |
| 1100 |
| 034 |
+--------+
Replaced the decimal sign as suggested by #isaac and #eric-brandt. Then only populated the number of values the upstream application needed.
LEFT(REPLACE((CONVERT(decimal(10, 2), dur) / 60),'.',''),3) AS HOURS,

Converting a 5 digit int into time

In a legacy system (SQL Server 2005) I have a column that stores a 5 digit integer (ie 86340) as time. The legacy application shows 86340 as 23:59:00. I am unsure how how to translate that 5 digit integer into a date-time data type using SQL.
SQL Server 2012+ has TIMEFROMPARTS function:
TIMEFROMPARTS ( hour, minute, seconds, fractions, precision )
Returns a time value for the specified time and with the specified precision.
Which is similiar to Excel's TIME:
TIME(hour, minute, second)
Excel version could handle values over 0-60 range:
Minute Required. A number from 0 to 32767 representing the minute. Any value greater than 59 will be converted to hours and minutes.
And SQL counterpart cannot do that.
It looks like that value is simply number of seconds so you could use:
DECLARE #A1 INT = 86340;
SELECT DATEADD(second, #A1,CAST('00:00:00' AS TIME));
DBFiddle Demo
EDIT:
As SQL Server 2005 does not support TIME data type, you could use DATETIME instead and skip date part in application.
DECLARE #A1 INT = 86340;
SELECT DATEADD(second, #A1,CAST('00:00:00' AS DATETIME));
DBFiddle Demo2
Since the value you have is an integer representation of the seconds since midnight, you have a couple of choices in SQL Server 2005. You can either render the value as a VARCHAR, which is readable, you can render it as DATETIME, which appends the date information, or you can maybe pull in a date from another field to get an meaningful DATETIME for your value.
SELECT CONVERT(VARCHAR(12), DATEADD(SECOND, 86340, 0), 114) AS [InVarchar];
+--------------+
| InVarchar |
+--------------+
| 23:59:00:000 |
+--------------+
SELECT DATEADD(SECOND, 86340, 0) AS [InDatetime];
+-------------------------+
| InDatetime |
+-------------------------+
| 1900-01-01 23:59:00.000 |
+-------------------------+
SELECT DATEADD(SECOND, 86340, CAST('2018-09-05' AS DATETIME)) AS [InDatetimeWithDate];
+-------------------------+
| InDatetimeWithDate |
+-------------------------+
| 2018-09-05 23:59:00.000 |
+-------------------------+
USE below query:
SELECT CONVERT(DATETIME, #Column_Name)
FROM Table;

How to round a number including least significant zeros?

I am trying to execute following SQL query in Oracle
Select round ( 123.50000065 , 4 ) from dual;
Output : 123.5
Required output: 123.5000
Any help is appreciated. ..
You probably want to use to_char with required format:
Below rounds the value to 4 decimal places and formats into the required string:
Select to_char(123.50000065, '999999999990D9999') x from dual;
If you don't want to actually round the number i.e. you just want to truncate after 4 digits, use:
Select to_char(trunc(123.50000065, 4), '999999999990D9999') x from dual;
ROUND ( numeric_expression , length [ ,function ] )
SELECT ROUND(123.9994, 3), ROUND(123.9995, 3);
Output:
123.9990 124.0000
Instead of round(), use to_char() or cast() to a decimal type:
select to_char(val, '999.9999'),
cast(val as decimal(10, 4))
To control the format a number is showed, you can cast it to a string, by applying the right format mask.
Depending on how you need round your input value, one of these could be useful:
with test(x) as (
select 123.50000065 from dual union all
select 123.00004 from dual union all
select 123.00005 from dual union all
select 123.00008 from dual
)
select x,
to_char(x, 'FM99999999.0000'),
to_char(trunc(x, 4), 'FM99999999.0000')
from test ;
result:
X TO_CHAR(X,'FM9 TO_CHAR(TRUNC(
-------------------------- -------------- --------------
123,50000065000 123.5000 123.5000
123,00004000000 123.0000 123.0000
123,00005000000 123.0001 123.0000
123,00008000000 123.0001 123.0000
"Rounding" is a mathematical concept. The value (with your sample input) is 123.5. Mathematically 123.5000 is the same thing as 123.5. They are only different as STRINGS.
One way to display 123.5 as 123.5000 is to wrap round() within to_char(). However, this means you are not able to use it in further computations (actually Oracle will allow you to - it will do an implicit conversion back to number instead of throwing a data type mismatch error, as it should do).
The better way, in most cases, is to address formatting in your client software, like SQL Developer, SQL*Plus, or Toad. Here is how you can do it in SQL*Plus:
SQL> Select round ( 123.50000065 , 4 ) as result from dual;
RESULT
----------
123.5
-- change the format of the numeric column "result"
SQL> column result format 999.0000
SQL> Select round ( 123.50000065 , 4 ) as result from dual;
RESULT
---------
123.5000
I can't see how you got 123.5 from your query. mine results 123.50000000
if I understand correctly, you want your number 4 significant decimal places.
why not try cast
select cast(123.50000065 as numeric(38,4))
output: 123.5000
testing if it rounds off number:
select cast(123.50000065 as numeric(38,6))
output: 123.500001

order by not formatted date sqlite

I'm storing Dates as string in the database with this format DD-MM-YYYY.
When I tried to make a select query with an orderby on the date column. I didn't get the expected result.
example of result :
28/02/2013
27/02/2013
01/03/2013
My sql query :
SELECT * FROM data ORDER BY strftime('%s', date_column)
Thank you.
The problem is that you store dates as DD-MM-YYYY strings, which does not only prevent natural ordering of dates as strings, but also parsing them with SQLite's date and time functions. Click the link and scroll down to 'Time Strings' section.
SQLite expects date/time strings in the natural order, most significant digit to least significant, that is, YYYY-MM-DD. You can use string operations to transform your DD-MM-YYYY strings into that form. For instance:
select
substr(reversed_date, 7,4) || '-' ||
substr(reversed_date, 4, 2)|| '-' ||
substr(reversed_date, 1, 2) as proper_date
from (
select '12-03-2000' as reversed_date
)
;
You can either transform your date column into this format (as #peterm suggests) or just use the value of proper_date for sorting. You don't need to use strftime for that, but date-related functions will work with such values.
IMHO you need to change the format you store dates in from
DD-MM-YYYY
to
YYYY-MM-DD
From docs
Time Strings
A time string can be in any of the following formats:
YYYY-MM-DD
YYYY-MM-DD HH:MM
YYYY-MM-DD HH:MM:SS
YYYY-MM-DD HH:MM:SS.SSS
YYYY-MM-DDTHH:MM
YYYY-MM-DDTHH:MM:SS
YYYY-MM-DDTHH:MM:SS.SSS
...
Then your original query and this one will work as expected
SELECT * FROM Table1 ORDER BY date(date_column);
SELECT * FROM Table1 ORDER BY strftime('%s', date_column);
Output:
| date_column |
---------------
| 2013-02-27 |
| 2013-02-28 |
| 2013-03-01 |
sqlfiddle
According to the documentation the following should work
SELECT *
FROM data
ORDER BY strftime('%Y-%m-%d', date_column)
try:
SELECT * FROM data ORDER BY to_date(date_column)
probably this might solve you problem as it is going for string comparison rather than date comparison so
01/03/2013 appears smaller than 28/02/2013 or 27/02/2013
thus output is :
01/03/2013, 27/02/2013, 28/02/2013
This query worked for me filter dates
SELECT inst.*,
Substr(columnname, 4, 2) AS newdate,
Substr(columnname, 0, 3) AS newday,
Substr(columnname, 12, 5) AS newtime
FROM table_name AS inst
WHERE child_id = id
ORDER BY newdate DESC, newday DESC, newtime DESC