Substring SQL Select statement - substring

I have a number of references with a length of 20 and I need to remove the 1st 12 numbers, replace with a G and select the next 7 numbers
An example of the format of the numbers being received
50125426598525412584
I then need to remove first 12 digits and select the next 7 (not including the last)
2541258
Lastly I need to put a G in front of the number so I'm left with
G25412584
My SQL is as follows:
SELECT SUBSTRING(ref, 12, 7) AS ref
FROM mytable
WHERE ref LIKE '5012%'
The results of this will leave me with
25412584
But how do I insert the G in front of the number in the same SQL statement?
Many thanks

SELECT 'G'+SUBSTRING(ref, 12, 7) AS ref FROM mytable where ref like '5012%'

SELECT CONCAT( 'G', SUBSTRING('50125426598525412584', 13,7)) from dual;

Related

How to give 0 at the beginning of hour or giving AM and PM in postgresql [duplicate]

I am relatively new to PostgreSQL and I know how to pad a number with zeros to the left in SQL Server but I'm struggling to figure this out in PostgreSQL.
I have a number column where the maximum number of digits is 3 and the min is 1: if it's one digit it has two zeros to the left, and if it's 2 digits it has 1, e.g. 001, 058, 123.
In SQL Server I can use the following:
RIGHT('000' + cast([Column1] as varchar(3)), 3) as [Column2]
This does not exist in PostgreSQL. Any help would be appreciated.
You can use the rpad and lpad functions to pad numbers to the right or to the left, respectively. Note that this does not work directly on numbers, so you'll have to use ::char or ::text to cast them:
SELECT RPAD(numcol::text, 3, '0'), -- Zero-pads to the right up to the length of 3
LPAD(numcol::text, 3, '0') -- Zero-pads to the left up to the length of 3
FROM my_table
The to_char() function is there to format numbers:
select to_char(column_1, 'fm000') as column_2
from some_table;
The fm prefix ("fill mode") avoids leading spaces in the resulting varchar. The 000 simply defines the number of digits you want to have.
psql (9.3.5)
Type "help" for help.
postgres=> with sample_numbers (nr) as (
postgres(> values (1),(11),(100)
postgres(> )
postgres-> select to_char(nr, 'fm000')
postgres-> from sample_numbers;
to_char
---------
001
011
100
(3 rows)
postgres=>
For more details on the format picture, please see the manual:
http://www.postgresql.org/docs/current/static/functions-formatting.html
As easy as
SELECT lpad(42::text, 4, '0')
References:
http://www.postgresql.org/docs/current/static/functions-string.html
sqlfiddle: http://sqlfiddle.com/#!15/d41d8/3665
The easiest way:
ltrim(to_char(Column1, '000'))

Breaking strings in a column by using a sliding window in PostgreSQL

How can I break each string in below column by using a sliding window in PostgreSQL.
Input
Column
TTTTACAATATAGCCAC
TTTGAAGAAAACATGCA
TTTCATACGGCTAGCGG
TTTAGTCTGTATGCTTG
For first string the expected output is below (sliding window = 9). I am expecting such output for every string of the column.
Output
TTTTACAAT
TTTACAATA
TTACAATAT
TACAATATA
ACAATATAG
CAATATAGC
AATATAGCC
ATATAGCCA
TATAGCCAC
Thanks
The generate_series function is your friend here.
https://www.postgresql.org/docs/current/functions-srf.html
Firstly you will need to split your string as such
WITH split AS(
SELECT generate_series(1, length('TTTTACAATATAGCCAC') - 8) AS start
)
SELECT substring('TTTTACAATATAGCCAC', split.start, 9)
FROM split;
Then, assuming you are getting it from a table, your query would go something like this.
WITH split AS(
SELECT
your_table_column as text,
generate_series(1, length(your_table_column) - 8) AS start
FROM your_table_name
)
SELECT substring(text, split.start, 9)
FROM split;
This will not display any columns that are below 9 characters, so other logic will need to be applied.

Adding leading zero if length is not equal to 10 digit using sql

I am trying to join 2 tables but my problem is that one of the table has 10 digit number and the other one may have 10 or less digit number. For this reason, i am loosing some data so i would like to do is check the length first if the length is less than 10 digit then i want to add leading zeros so i can make it 10 digit number. I want to do this when i am joining this so i am not sure if this is possible. Here is an example if i i have 251458 in the TABLE_WITHOUT_LEADING_ZERO then i want to change it like this: 0000251458. Here is what i have so far:
select ACCT_NUM, H.CODE
FROM TABLE_WITH_LEEDING_ZERO D, TABLE_WITHOUT_LEADING_ZERO H
WHERE substring(D.ACCT_NUM from position('.' in D.ACCT_NUM) + 2) = cast (H.CODE as varchar (10))
thanks
Another alternative:
SELECT TO_CHAR(12345,'fm0000000000');
to_char
------------
0000012345
In Netezza you can use LPAD:
select lpad(s.sample,10,0) as result
from (select 12345 as sample) s
result
-------
0000012345
However it would be more efficient to remove the zeros like in the example below:
select cast(trim(Leading '0' from s.sample) as integer) as result
from (select '0000012345' as sample) s
result
-------
12345

Recursive replace from a table of characters

In short, I am looking for a single recursive query that can perform multiple replaces over one string. I have a notion it can be done, but am failing to wrap my head around it.
Granted, I'd prefer the biz-layer of the application, or even the CLR, to do the replacing, but these are not options in this case.
More specifically, I want to replace the below mess - which is C&P in 8 different stored procedures - with a TVF.
SET #temp = REPLACE(RTRIM(#target), '~', '-')
SET #temp = REPLACE(#temp, '''', '-')
SET #temp = REPLACE(#temp, '!', '-')
SET #temp = REPLACE(#temp, '#', '-')
SET #temp = REPLACE(#temp, '#', '-')
-- 23 additional lines reducted
SET #target = #temp
Here is where I've started:
-- I have a split string TVF called tvf_SplitString that takes a string
-- and a splitter, and returns a table with one row for each element.
-- EDIT: tvf_SplitString returns a two-column table: pos, element, of which
-- pos is simply the row_number of the element.
SELECT REPLACE('A~B!C#D#C!B~A', MM.ELEMENT, '-') TGT
FROM dbo.tvf_SplitString('~-''-!-#-#', '-') MM
Notice I've joined all the offending characters into a single string separated by '-' (knowing that '-' will never be one of the offending characters), which is then split. The result from this query looks like:
TGT
------------
A-B!C#D#C!B-A
A~B!C#D#C!B~A
A~B-C#D#C-B~A
A~B!C-D-C!B~A
A~B!C#D#C!B~A
So, the replace clearly works, but now I want it to be recursive so I can pull the top 1 and eventually come out with:
TGT
------------
A-B-C-D-C-B-A
Any ideas on how to accomplish this with one query?
EDIT: Well, actual recursion isn't necessary if there's another way. I'm pondering the use of a table of numbers here, too.
You can use this in a scalar function. I use it to remove all control characters from some external input.
SELECT #target = REPLACE(#target, invalidChar, '-')
FROM (VALUES ('~'),(''''),('!'),('#'),('#')) AS T(invalidChar)
I figured it out. I failed to mention that the tvf_SplitString function returns a row number as "pos" (although a subquery assigning row_number could also have worked). With that fact, I could control cross join between the recursive call and the split.
-- the cast to varchar(max) matches the output of the TVF, otherwise error.
-- The iteration counter is joined to the row number value from the split string
-- function to ensure each iteration only replaces on one character.
WITH XX AS (SELECT CAST('A~B!C#D#C!B~A' AS VARCHAR(MAX)) TGT, 1 RN
UNION ALL
SELECT REPLACE(XX.TGT, MM.ELEMENT, '-'), RN + 1 RN
FROM XX, dbo.tvf_SplitString('~-''-!-#-#', '-') MM
WHERE XX.RN = MM.pos)
SELECT TOP 1 XX.TGT
FROM XX
ORDER BY RN DESC
Still, I'm open to other suggestions.

Perl + PostgreSQL-- Selective Column to Row Transpose

I'm trying to find a way to use Perl to further process a PostgreSQL output. If there's a better way to do this via PostgreSQL, please let me know. I basically need to choose certain columns (Realtime, Value) in a file to concatenate certains columns to create a row while keeping ID and CAT.
First time posting, so please let me know if I missed anything.
Input:
ID CAT Realtime Value
A 1 time1 55
A 1 time2 57
B 1 time3 75
C 2 time4 60
C 3 time5 66
C 3 time6 67
Output:
ID CAT Time Values
A 1 time 1,time2 55,57
B 1 time3 75
C 2 time4 60
C 3 time5,time6 66,67
You could do this most simply in Postgres like so (using array columns)
CREATE TEMP TABLE output AS SELECT
id, cat, ARRAY_AGG(realtime) as time, ARRAY_AGG(value) as values
FROM input GROUP BY id, cat;
Then select whatever you want out of the output table.
SELECT id
, cat
, string_agg(realtime, ',') AS realtimes
, string_agg(value, ',') AS values
FROM input
GROUP BY 1, 2
ORDER BY 1, 2;
string_agg() requires PostgreSQL 9.0 or later and concatenates all values to a delimiter-separated string - while array_agg() (v8.4+) creates am array out of the input values.
About 1, 2 - I quote the manual on the SELECT command:
GROUP BY clause
expression can be an input column name, or the name or ordinal number
of an output column (SELECT list item), or ...
ORDER BY clause
Each expression can be the name or ordinal number of an output column
(SELECT list item), or
Emphasis mine. So that's just notational convenience. Especially handy with complex expressions in the SELECT list.