How do I format a number of arbitrary length? - postgresql

If I have data that includes a numeric column with values into the miillions (eg 63254830038), and I want to format the number as a US Dollar amount (eg. $63,254,830,038), I know I can use:
SELECT numeric_column, to_char(numeric_column, '$999G999G999G999') from table
to format the values, but to do so reliably I either have to include an unnecessarily long text string ('$999G999G999G999') or know the maximum number of possible digits. Is there a way to say, broadly, "group numbers with a comma" instead of explicitly saying "group the hundreds, group the thousands, Oh! and please group the millions"?

You just need cast integer to money type.
E.g.:
tests=> select cast(63254830038 as money);
Or alternative syntax:
tests=> select 6323254830038::money;
And output (I'm from Poland, so money type take my locales and set correct currency symbol):
money
----------------------
63.254.830.038,00 zł
Monetary Types documentation.

You can try something like this (works in sql-server, not sure about postgresql)
select convert(varchar,cast('63254830038' as money),1)

You could do things the hard way using regular expressions: convert the number into a string, reverse it, use regexp_replace to insert commas between pairs of 3 digits, and then reverse it again:
select '$' || reverse(regexp_replace(
reverse(numeric_column::varchar),
E'(\\d\\d\\d)(?=\\d)', '\1,', 'g'))
Explanation
The first argument to regexp_replace is the expression to match, which contains two parts:
(\\d\\d\\d) means 3 digits, which are captured
(?=\\d) is a positive lookahead constraint of a single digit, meaning the match only counts if there is a digit following it. (That is, this digit is checked to exist, but it does not count as part of the match.)
The second argument is what to replace with: the 3 captured digits, plus a comma.
The third argument 'g' is a flag indicating that it should match and replace as many times as possible.
For more information on regular expressions in PostgreSQL, see the documentation.

Related

Delete specific digit in a number using PostgreSQL

I have a column named membership_number varchar(255) in the memberships table.
Here is some sample data:
0000001234
0000002345
0000003456
membership_number must have 10 digits. If a user enters a number that has less than 10 digits, then the missing places are filled with leading zeroes accordingly.
At the moment, I have some data in this column as follows:
00001234.0
00002345.1
00003456.2
I would like to delete the decimal point which is the 2nd to the last digit and then add a leading zero to handle all of these undesired membership numbers. What would be the best way to do this?
I am aware of SUBSTRING() and its parameters but couldn't make it work so far.
Please backup your data before trying this.
Would that work?
UPDATE tablename SET membership_number = concat('0',replace(membership_number,'.','')) WHERE membership_number LIKE '%._'
Substring is not the function you want, you want a combination of REPLACE and LPAD functions:
select lpad( replace (membership_number, '.', ''), 10, '0')
from menberships;
(table name assumed) And why if it must be 10 digits do you define it as length up to 255?

How to replace second occurrence of word in postgre sql using SQL?

Eg.
select regex_replace('the growth is growth for', '?','good','ig');
it should return
the growth is good for
You can match the word you are looking for, followed by everything up to the 2nd word, followed by the word you are looking for again, then replace it with the first two matches, followed by the word you want to replace it with.
For example:
SELECT regexp_replace(
'the growth is growth for lots of growth',
'(growth)(.*?)(\1)',
'\1\2good', 'ig'
);
regexp_replace
---------------------------------------
the growth is good for lots of growth
(1 row)
Here, the (.*?) is matching everything after the first "growth" text, but to stop matching once it hits the next "growth" text, denoted by \1, meaning whatever was matched in the first group enclosed in parentheses. The ? character makes it non-greedy, matching the minimum needed. If it weren't there, it would match as much as it can, which would keep going if there were more than 2 instances to only replace the last.

How to get one letter and one number from REGEX Oracle Sql query

Trying to get just "P1:" from this code but if I add numbers to the one it will output those as well. How do I restrict it to only take numbers 1-9 and have it display "NULL" if it's two digits?
select REGEXP_SUBSTR('P1:EMAIL', '[P]+\d+[:]') as test from dual;
You have included the + operator, which means match one or more of the character or class. If you want to match exactly one then you don't want that. You also don't need the square brackets:
select REGEXP_SUBSTR('P1:EMAIL', 'P\d:') as test from dual;
You might also want to anchor the pattern to the start of the string, but that isn't clear; if so then:
select REGEXP_SUBSTR('P1:EMAIL', '^P\d:') as test from dual;

Pulling a Substring which does not exist in the same position

I am looking to pull a substring from a Oracle database column using PL/SQL.
The column has a large string value which varies in size for different rows. Hence the substring I am referring to will not be in the same position for each row. But the substring is uniquely identifiable. It will be like ",RID!1455,". i.e. It will be preceded by a comma, have RID, followed by a !, followed by a number and then a comma.
I am interested in pulling this number followed by RID. Can you please help me with this. Thank you very much in advance
Consider below query:
Suppose table text1 has column text with string:
dfgggsdRID!3242dfgdfdg
Then below query will give you result '3242':
select substr(text, (select (INSTR(text, 'RID!', 1)+4) FROM text1),4) from text1;

Converting / Casting an nVarChar with Comma Separator to Decimal

I am supporting an ETL process that transforms flat-file inputs into a SqlServer database table. The code is almost 100% T-SQL and runs inside the DB. I do not own the code and cannot change the workflow. I can only help configure the "translation" SQL that takes the file data and converts it to table data (more on this later).
Now that the disclaimers are out of the way...
One of our file providers recently changed how they represent a monetary amount from '12345.67' to '12,345.67'. Our SQL that transforms the value looks like SELECT FLOOR( CAST([inputValue] AS DECIMAL(24,10))) and no longer works. I.e., the comma breaks the cast.
Given that I have to store the final value as Decimal (24,10) datatype (yes, I realize the FLOOR wipes out all post-decimal-point precision - the designer was not in sync with the customer), what can I do to cast this string efficiently?'
Thank you for your ideas.
try using REPLACE (Transact-SQL):
SELECT REPLACE('12,345.67',',','')
OUTPUT:
12345.67
so it would be:
SELECT FLOOR( CAST(REPLACE([input value],',','') AS DECIMAL(24,10)))
This works for me:
DECLARE #foo NVARCHAR(100)
SET #foo='12,345.67'
SELECT FLOOR(CAST(REPLACE(#foo,',','') AS DECIMAL(24,10)))
This is probably only valid for collations/culture where the comma is not the decimal separator (ie: Spanish)
While not necessarily the best approach for my situation, I wanted to leave a potential solution for future use that we uncovered while researching this problem.
It appears that the SqlServer datatype MONEY can be used as a direct cast for strings with a comma separating the non-decimal portion. So, where SELECT CAST('12,345.56' AS DECIMAL(24,10)) fails, SELECT CAST('12,345.56' AS MONEY) will succeed.
One caveat is that the MONEY datatype has a precision of 4 decimal places and would require an explicit cast to get it to DECIMAL, should you need it.
SELECT FLOOR (CAST(REPLACE([inputValue], ',', '') AS DECIMAL(24,10)))