Migrate SQL Server functions to PostgreSQL - sql-server

How can I do these same conversions that are written in SQL Server to PostgreSQL.
These are the data I receive:
#AVLData_GPSElement_Longitude #AVLData_GPSElement_Latitude
D224E31D F8C95DB9
This is the conversion that is written in SQL Server.
SUBSTRING(CONVERT(VARCHAR(50), CONVERT(INT, CONVERT(VARBINARY, #AVLData_GPSElement_Latitude, 2))), 1, 3) + '.' + SUBSTRING(CONVERT(VARCHAR(50), CONVERT(INT, CONVERT(VARBINARY, #AVLData_GPSElement_Latitude, 2))), 4, 7)
SUBSTRING(CONVERT(VARCHAR(50), CONVERT(INT, CONVERT(VARBINARY, #AVLData_GPSElement_Longitude, 2))), 1, 3) + '.' + SUBSTRING(CONVERT(VARCHAR(50), CONVERT(INT, CONVERT(VARBINARY, #AVLData_GPSElement_Longitude, 2))), 4, 7)
and the result it gives is the following:
#MOPO_LAT #MOPO_LON
-12.102099900 -76.933449900
So far I have managed to do this conversion so far:
SUBSTRING(CONVERT(VARBINARY, AVLData_GPSElement_Latitude, 2)::INTEGER ::VARCHAR FROM 1 FOR 3) + '.' + SUBSTRING(CONVERT(VARBINARY, AVLData_GPSElement_Latitude, 2)::INTEGER ::VARCHAR) FROM 4 FOR 7);
but my big question arises in this function:
CONVERT (VARBINARY, #AVLData_GPSElement_Latitude, 2)
I don't know how to translate it because I don't find much information about it.
I am working on conversions of teltonika fm920 gps equipment.
I appreciate your help in advance.

This function is first converting hex to an integer. F8C95DB9 is -121020999. Use the technique here. Stick an x on the front so bit(32) will cast it as hex, then cast that to a 32 bit integer.
select ('x'||'F8C95DB9')::bit(32)::int4
int4
------------
-121020999
Then divide by 10000000.0.
select ('x'||'F8C95DB9')::bit(32)::int4 / 10000000.0 as lat;
lat
----------------------
-12.1020999000000000
And at that point I would stop and leave further formatting to the display layer.
Note: If you're working with Latitude and Longitude, consider PostGIS.

Related

Fix datetime string in SQL Server

I have a table with 43 000 000 rows. In datetime column data looks 2020.04.22T04:39:29.359 and it's of type VARCHAR.
It looks like an ISO format but there are ., and for ISO I need -.
What is the best way to convert the values in these rows to datetime?
One of my variant was subst . to -:
UPDATE table
SET [Column 3] = REPLACE([Column 3], '.', '-');
but then I need to cut a microseconds from the end.
How to do this cut?
Or maybe you can advice more truish way.
You may use TRY_CONVERT here, after first doing a bit of massaging to bring your raw datetime strings into a format which SQL Server recognizes:
UPDATE yourTable
SET new_dt_col = TRY_CONVERT(
datetime,
REPLACE(LEFT(dt_col, 19), '.', '-') + '.' + RIGHT(dt_col, 3)
);
To be explicit, the replacement logic used above would first convert this:
2020.04.22T04:39:29.359
into this:
2020-04-22T04:39:29.359
You may verify for yourself that the following conversion works correctly:
SELECT TRY_CONVERT(datetime, '2020-04-22T04:39:29.359');
If every single row in the table has the date that follows the format 2020.04.22T04:39:29.359 you can do the following update statement:
UPDATE table
SET [Column 3] = SUBSTRING([Column 3],1,4) + '-' + SUBSTRING([Column 3],6,2) + '-' + SUBSTRING([Column 3],9,15)
To only fix the 5th and 8th character without affecting the "." character from the microseconds.
After that you should be able to do the conversion to datetime.

Why in sql server can't return proper error in decimal data type conversion? [duplicate]

This question already has answers here:
VARCHAR to DECIMAL
(12 answers)
Closed 3 years ago.
When I write query like
Select 3 + '44. 5'
It gave me error conversion failed when converting varchar value to '44. 6' to data type int
Why it can not return proper error for decimal cannot converting to int.
Remove the single quote. The quote means that it is a string value not a real number value.
SELECT 3 + 44.5
There are two possible outputs you might want: 47.5 as a number, or 344.5 as a string:
SELECT 3 + CAST( '44.5' as decimal(3,1))
OR...
SELECT CONCAT(CAST(3 as varchar), '44.5')
First, this page will tell you everything you need to know about this topic (and can be used to cure insomnia): Data type conversion (Database Engine)
Next, what you posted is '44. 5' that cant be converted into a number. This fails no matter what numeric data type you try:
SELECT CAST('44. 5' AS NUMERIC)
This will fail because SQL can't determine if you're aggregating numbers or concatenating text:
Select 3 + '44.6';
These will work for math:
Select 3 + 44.5;
Select 3 + CAST('44.5' AS DECIMAL(3,1));
Select CAST(3 AS DECIMAL(3,1)) + '44.5';
These will work for concatination:
Select '3' + '44.5';
Select CAST(3 AS VARCHAR(10)) + '44.5'
Select CONCAT(3, '44.5');

Convert from 4 digit Military time to Standard time

I am using SQL Server 2016 and I'm trying to convert military time to standard time. The military time is a 4 digit integer and I'm trying to get the standard time format (00:00 am/pm).
I ran a simple CASE statement that made it standard but without ':' and 'am/pm'.
CASE
WHEN SA_BEGTIME between 0 and 1259 then SA_BEGTIME
WHEN SA_BEGTIME between 1300 and 2400 then SA_BEGTIME - 1200
ELSE ''
END as Time
Results
How do I convert it so that it is in the right format: '00:00 am/pm'
Thank you!
You can split it into parts with integer division and modulo, cast it to a VARCHAR and then you can convert it to a TIME:
declare #x int = 109
select cast(cast(#x / 100 as varchar(2)) + ':' + cast(#x % 100 as varchar(2)) as time)
Or you can use the new TIMEFROMPARTS() function (SQL Server 2012+):
declare #x int = 109
select TIMEFROMPARTS(#x / 100,#x % 100, 0, 0, 0)
You can then format it however you'd like.
Assuming your data is stored as an integer, and also assuming there is not invalid time stored (i.e. values above 2400 or below 0) you can use the following:
declare #TheTime int = 900
select right(convert(varchar(20),
cast(stuff(right('0000' + convert(varchar(4),#TheTime),4),3,0,':')
as datetime),100),7)
-------
9:00AM
Sorry for the density of the solution. This is what I did:
Convert #TheTime to varchar(4)
Add a string of zeros at the front
Take the rightmost 4 characters from this new string
Stuff a colon sign in the middle of this new string
Cast the string as datetime
Convert back to string using 100 as the style indicator to get AM/PM
Get the right most 7 characters of the string.
I am sure there are more elegant ways, but this one works for me quite well.
I'm using the solution that #BaconBits provided but I had to make a tweak because 2400 was a valid representation but it failed with that code. Here's the tweaked solution:
declare #x int = 2400
select TIMEFROMPARTS((#x / 100) % 24,#x % 100, 0, 0, 0)
I needed to convert a datetime field where the time was military to just the time in AM/PM format. This worked beautifully.
Left(convert(varchar(20), cast(MyDateField as time),100),7)
You can use convert to get n appropriate presentation of time.
declare #mt varchar(4) = '1500'
select convert(varchar, cast(left(#mt, 2) + ':' + right(#mt, 2) as time), 0)

String of date time convert to date time in SQL Server

I have this string which is a combination of date and time but in string format meaning that it has no space. I parsed it from a very long string but I now have or need to convert it to a standard date and time.
This is my string for date and time:
141007024755
This is how I parsed it from a very long string of data
[date&time] = SUBSTRING(#ProductCode, 27, 12)
This is the format I'm expecting but can't do it.
2014-10-07 02:47:55.000
Can anyone give me a hint on how to do this? An advice perhaps.
Thanks.
If the string is always 12 characters long you could try this:
select cast(stuff(stuff(stuff('141007024755', 7,0,' '), 10,0,':'), 13,0,':') as datetime)
Basically it uses the stuff function to insert a space between the date and time parts and colons between the different time parts producing a string like141007 02:47:55that can be converted todatetimeusingcast.
Assuming the dates are formatted exactly as your sample string, you can just keep chopping up the string and appending it back together and cast the result to date. Simple function like this may help:
CREATE FUNCTION dbo.udf_ReturnDateFromString(#DateString AS VARCHAR(14))
RETURNS DATETIME
AS
BEGIN
SET #DateString = '20' + #DateString
RETURN CAST(LEFT(#DateString, 4) + '-' +
SUBSTRING(#DateString, 5, 2) + '-' +
SUBSTRING(#DateString, 7, 2) + ' ' +
SUBSTRING(#DateString, 9, 2) + ':' +
SUBSTRING(#DateString, 11, 2) + ':' +
SUBSTRING(#DateString, 13, 2) AS DATETIME)
END;
GO
SELECT dbo.udf_ReturnDateFromString('141007024755');
The result is:
2014-10-07 02:47:55.000
You get the idea. This was done on SS 2008 R2.

Convert float into varchar in SQL Server without scientific notation

Convert float into varchar in SQL Server without scientific notation and trimming decimals.
For example:
I have the float value 1000.2324422, and then it would be converted into varchar as same 1000.2324422.
There could be any number of decimal values...the float value comes randomly.
Casting or converting to VARCHAR(MAX) or anything else did not work for me using large integers (in float fields) such as 167382981, which always came out '1.67383e+008'.
What did work was STR().
Neither str() or cast(float as nvarchar(18)) worked for me.
What did end up working was converting to an int and then converting to an nvarchar like so:
convert(nvarchar(18),convert(bigint,float))
The STR function works nice. I had a float coming back after doing some calculations and needed to change to VARCHAR, but I was getting scientific notation randomly as well. I made this transformation after all the calculations:
ltrim(rtrim(str(someField)))
Try CAST(CAST(#value AS bigint) AS varchar)
This works:
CONVERT(VARCHAR(100), CONVERT(DECIMAL(30, 15), fieldname))
Try this:
SELECT REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(REPLACE(CAST(CAST(YOUR_FLOAT_COLUMN_NAME AS DECIMAL(18,9)) AS VARCHAR(20)),'0',' ')),' ','0'),'.',' ')),' ','.') FROM YOUR_TABLE_NAME
Casting as DECIMAL will put decimal point on every value, whether it
had one before or not.
Casting as VARCHAR allows you to use the REPLACE function
First REPLACE zeros with spaces, then RTRIM to get rid of all trailing spaces (formerly zeros), then REPLACE remaining spaces with zeros.
Then do the same for the period to get rid of it for numbers with no decimal values.
This is not relevant to this particular case because of the decimals, but may help people who google the heading.
Integer fields convert fine to varchars, but floats change to scientific notation. A very quick way to change a float quickly if you do not have decimals is therefore to change the field first to an integer and then change it to a varchar.
Below is an example where we can convert float value without any scientific notation.
DECLARE #Floater AS FLOAT = 100000003.141592653
SELECT CAST(ROUND(#Floater, 0) AS VARCHAR(30))
,CONVERT(VARCHAR(100), ROUND(#Floater, 0))
,STR(#Floater)
,LEFT(FORMAT(#Floater, ''), CHARINDEX('.', FORMAT(#Floater, '')) - 1)
SET #Floater = #Floater * 10
SELECT CAST(ROUND(#Floater, 0) AS VARCHAR(30))
,CONVERT(VARCHAR(100), ROUND(#Floater, 0))
,STR(#Floater)
,LEFT(FORMAT(#Floater, ''), CHARINDEX('.', FORMAT(#Floater, '')) - 1)
SET #Floater = #Floater * 100
SELECT CAST(ROUND(#Floater, 0) AS VARCHAR(30))
,CONVERT(VARCHAR(100), ROUND(#Floater, 0))
,STR(#Floater)
,LEFT(FORMAT(#Floater, ''), CHARINDEX('.', FORMAT(#Floater, '')) - 1)
SELECT LEFT(FORMAT(#Floater, ''), CHARINDEX('.', FORMAT(#Floater, '')) - 1)
,FORMAT(#Floater, '')
In the above example, we can see that the format function is useful for us. FORMAT() function returns always nvarchar.
I have another solution since the STR() function would result some blank spaces, so I use the FORMAT() function as folowing example:
SELECT ':' + STR(1000.2324422), ':' + FORMAT(1000.2324422,'##.#######'), ':' + FORMAT(1000.2324422,'##')
The result of above code would be:
: 1000 :1000.2324422 :1000
You can use this code:
STR(<Your Field>, Length, Scale)
Your field = Float field for convert
Length = Total length of your float number with Decimal point
Scale = Number of length after decimal point
For example:
SELECT STR(1234.5678912,8,3)
The result is: 1234.568
Note that the last digit is also round up.
You will have to test your data VERY well. This can get messy. Here is an example of results simply by multiplying the value by 10. Run this to see what happens.
On my SQL Server 2017 box, at the 3rd query I get a bunch of *********. If you CAST as BIGINT it should work every time. But if you don't and don't test enough data you could run into problems later on, so don't get sucked into thinking it will work on all of your data unless you test the maximum expected value.
Declare #Floater AS FLOAT =100000003.141592653
SELECT CAST(ROUND(#Floater,0) AS VARCHAR(30) ),
CONVERT(VARCHAR(100),ROUND(#Floater,0)),
STR(#Floater)
SET #Floater =#Floater *10
SELECT CAST(ROUND(#Floater,0) AS VARCHAR(30) ),
CONVERT(VARCHAR(100),ROUND(#Floater,0)),
STR(#Floater)
SET #Floater =#Floater *100
SELECT CAST(ROUND(#Floater,0) AS VARCHAR(30) ),
CONVERT(VARCHAR(100),ROUND(#Floater,0)),
STR(#Floater)
There are quite a few answers but none of them was complete enough to accommodate the scenario of converting FLOAT into NVARCHAR, so here we are.
This is what we ended up with:
DECLARE #f1 FLOAT = 4000000
DECLARE #f2 FLOAT = 4000000.43
SELECT TRIM('.' FROM TRIM(' 0' FROM STR(#f1, 30, 2))),
TRIM('.' FROM TRIM(' 0' FROM STR(#f2, 30, 2)))
SELECT CAST(#f1 AS NVARCHAR),
CAST(#f2 AS NVARCHAR)
Output:
------------------------------ ------------------------------
4000000 4000000.43
(1 row affected)
------------------------------ ------------------------------
4e+006 4e+006
(1 row affected)
In our scenario the FLOAT was a dollar amount to 2 decimal point was sufficient, but you can easily increase it to your needs.
In addition, we needed to trim ".00" for round numbers.
Try this code
SELECT CONVERT(varchar(max), CAST(1000.2324422 AS decimal(11,2)))
Result:
1000.23
Here decimal(11,2): 11-total digits count (without the decimal point), 2 - for two digits after the decimal point
None of the previous answers for me. In the end I simply used this:
INSERT INTO [Destination_Table_Name]([Field_Name])
SELECT CONCAT('#',CAST([Field_Name] AS decimal(38,0))) [Field_Name]
FROM [dbo].[Source_Table_Name] WHERE ISNUMERIC([CIRCUIT_NUMBER]) = 1
INSERT INTO [Destination_Table_Name]([Field_Name])
SELECT [Field_Name]
FROM [dbo].[Source_Table_Name] WHERE ISNUMERIC([CIRCUIT_NUMBER]) <> 1
select format(convert(float,#your_column),'0.0#########')
Advantage: This solution is independent of the source datatype (float, scientific, varchar, date, etc.)
String is limited to 10 digits, and bigInt gets rid of decimal values.
This works:
Suppose
dbo.AsDesignedBites.XN1E1 = 4016519.564`
For the following string:
'POLYGON(('+STR(dbo.AsDesignedBites.XN1E1, 11, 3)+'...

Resources