Get string after ',' delimeter comma or special characters - postgresql

The field name is message, table name is log.
Data Examples:
Values for message:
"(wsname,cmdcode,stacode,data,order_id) values (hyd-l904149,2,1,,1584425657892);"
"(wsname,cmdcode,stacode,data,order_id) values (hyd-l93mt54,2,1,,1584427657892);"
(command_execute,order_id,workstation,cmdcode,stacode,application_to_kill,application_parameters) values (kill, 1583124192811, hyd-psag314, 10, 2, tsws.exe, -u production ); "
and in log table i need to get separated column wsname with values as hyd-l904149 and hyd-l93mt54 and hyd-psag314, column cmdcode with values as 2,2 and 10 and column stacode with values as 1,1 and 2, e.g.:
wsname cmdcode stacode
hyd-l904149 2 1
hyd-l93mt54 2 1
hyd-psag314 10 2

Use regexp_matches to extract left and right part of values clause, then regexp_split_to_array to split these parts by commas, then filter rows containing wsname using = any(your_array) construct, then select required columns from array.
Or - alternative solution - fix data to be syntactically valid part of insert statement, create auxiliary tables, insert data into them and then just select.

As in comment section I mentioned about inbuilt function in posgressql
split_part(string,delimiter, field_number)
http://www.sqlfiddle.com/#!15/eb1df/1

As the json capabilities of the un-supported version 9.3 are very limited, I would install the hstore extension, and then do it like this:
select coalesce(vals -> 'wsname', vals -> 'workstation') as wsname,
vals -> 'cmdcode' as cmdcode,
vals -> 'stacode' as stacode
from (
select hstore(regexp_split_to_array(e[1], '\s*,\s*'), regexp_split_to_array(e[2], '\s*,\s*')) as vals
from log l,
regexp_matches(l.message, '\(([^\)]+)\)\s+values\s+\(([^\)]+)\)') as x(e)
) t
regexp_matches() splits the message into two arrays: one for the list of column names and one for the matching values. These arrays are used to create a key/value pair so that I can access the value for each column by the column name.
If you know that the positions of the columns are always the same, you can remove the use of the hstore type. But that would require quite a huge CASE expression to test where the actual columns appear.
Online example
With a modern, supported version of Postgres, I would use jsonb_object(text[], text[]) passing the two arrays resulting from the regexp_matches() call.

Related

Split column to many columns in PostgresQL

I have a table like:
id Name f_data
1 Raj {"review":"perfect", "tech":{"scalability":"complete", "backbonetech":["satellite"], "lastmiletech":["Fiber","Wireless","DSL"] }}
I want to split f_data column to multiple columns. Expected result:
id Name review scalability backbonetech lastmiletech
1 Raj perfect complete satellite Fiber,wireless,DSL
when I tray split json column I couldn't remove the bracket. My output is:
id Name review scalability backbonetech lastmiletech
1 Raj perfect complete ["satellite"] ["Fiber","wireless","DSL"]
I used this code:
SELECT id, Name,
f_data->'review' ->>0 as review,
f_data->'tech' ->> 'scalability' as scalability,
f_data->'tech' ->> 'backbonetech' as backbonetech,
f_data->'tech' ->> 'lastmiletech' as lastmileteck
from my_table;
One possibility is to use the json_array_elements_text function to transform the arrays in your JSON into a set of text and then use the string_agg function to concatenate the individual elements into a single string.
For lastmiletech, the request might look like :
select
string_agg(t.lastmiletech, ',') as lastmiletech
from
(
select
json_array_elements_text('{"scalability":"complete", "backbonetech":>["satellite"], "lastmiletech":["Fiber","Wireless","DSL"]}'::json->'lastmiletech') as lastmiletech
) t
You can modify the subquery to include the additional fields you need.
As the name imply, the first parameter of the json_array_elements_text has to be a json array, so be careful not to convert the array into text before passing it to the function. In other words, f_data->tech->>lastmiletech will not be accepted.

Data flow single row transformation

I have a transformation can this achieved by dataflow.
Thanks
ANuj Gupta
If the column data CN=SERVICE NOW,OU=TOOL;CN=PYTHON,OU=LANGUAGE;CN=ADF,OU=CLOUD schema is fixed, then you can use data flow derived column expression to achieve it.
I just made an example to get output, here's the dataset:
Data Flow derived column expressions:
Col1 column value: col1 --> {Col1 }
a column value: SERVICE NOW-->substring(split({ Col2},';')[1], 5, length(split({ Col2},';')[1])-12)
b column value: PYTHON --> substring(split({ Col2},';')[2], 4, length(split({ Col2},';')[1])-17)
c column value: ADF --> substring(split({ Col2},';')[3], 4, length(split({ Col2},';')[1])-20)
Screenshots:
But if the data is dynamic, we can't do the conversion in Data Factory, it's unachievable.
Logic : You can get the index of first occurence of 'CN=' and first occurence of comma to get first word between them, ie Service Now.
Similarly for others.
If I get time I will try to edit this with the actual syntax!
The strings are delimited by ;. First split by that(so you get an array) in a derived transform. You can then use the 'map' function to extract out the string before the last =. You will have an array of values(ADF/Python etc). Then you use a flatten transform to convert columns to rows.

Postgres: Query Values in nested jsonb-structure with unknown keys

I am quite new in working with psql.
Goal is to get values from a nested jsonb-structure where the last key has so many different characteristics it is not possible to query them explicitely.
The jsonb-structure in any row is as follows:
TABLE_Products
{'products':[{'product1':['TYPE'], 'product2':['TYPE2','TYPE3'], 'productN':['TYPE_N']}]}
I want to get the values (TYPE1, etc.) assigned to each product-key (product1, etc.). The product-keys are the unknown, because of too many different names.
My work so far achieves to pull out a tuple for each key:value-pair on the last level. To illustrate this here you can see my code and the results from the previously described structure.
My Code:
select url, jsonb_each(pro)
from (
select id , jsonb_array_elements(data #> '{products}') as pro
from TABLE_Products
where data is not null
) z
My result:
("product2","[""TYPE2""]")
("product2","[""TYPE3""]")
My questions:
Is there a way to split this tuple on two columns?
Or how can I query the values kind of 'unsupervised', so without knowing the exact names of 'product1 ... n'

comma separated field and comma separated search data

I can do this:
SELECT id, name, data FROM public.app
WHERE data=ANY(string_to_array('25,2,3,15', ',')::character varying[])
this is work correctly. But data field varchar and it will hold data which comma separated. In summary,
searching data= 25,2,3,15
db.field data=3,0,2,15,3,15 etc. both side include comma separated data.
I try this:
SELECT id, name, data FROM public.app
WHERE string_to_array(data,',')=ANY(string_to_array('25,2,3,15', ',')::character varying[])
but it is not working.
You are currently comparing two arrays using ANY when that is incorrect.
If you want to see if the two arrays are identical in their contents, you can simply remove ANY:
string_to_array(data,',') = (string_to_array('25,2,3,15', ',')::character varying[])
If you want to see if there is overlap between the two arrays, you use &&:
string_to_array(data,',') && (string_to_array('25,2,3,15', ',')::character varying[])
Additional operators are available here: https://www.postgresql.org/docs/current/static/functions-array.html

Is it possible to sort a number with alphabet in oracle10g

I have data like abc1, abc2, abcK. The result after sort should display like abcK, abc1, abc2.
Is there any way to achieve this?
Specify a different collating sequence, either by using ALTER SESSION to change the collating sequence for your entire session or by using NLSSORT to change the collating sequence for a single ORDER BY. For example,
SELECT *
FROM YOUR_TABLE
ORDER BY NLSSORT(YOUR_COLUMN, 'NLS_SORT=WEST_EUROPEAN')
will order letters before numbers. SQLFiddle here
Share and enjoy.
You could use a CASE expression in the ORDER BY clause.
For example,
order by
case when translate(column,'x0123456789','x') is null then 2
else 1
end, column;
The TRANSLATE would evaluate the pure strings as NULL. Thus, the case would return 2, else for all others, 1. Thus, any string having a number, i.e. alphanumeric values would be below the pure alphabets.