talend - filename of output from a column value - talend

I have an existing job:
tDatabaseInput ->
tMap ->
tOutputDelimited
For the last component, I need the filename of the file to be based from one of the columns named TYPE (which is always the same for every row). The value for the column named TYPE is 'A1' which is the same for all the records in the database.

There is many ways to do it, but here is the simplest and more readable job :
tMySqlConnection_1 : Get a connection to the data base server
tMysqlInput_1: Query the table an get only the value like this :
select TYPE from my_table limit 1
tSetGlobalVar_1 : key = "file_name", value = (String)row1.type
tMysqlInput_2 : uqery the table as required
tMap_1 : map your data
tFileOutputDelimited_1 : filename = "C:\\Users\\KKL\\Desktop\\"+((String)globalMap.get("file_name"))

You'll need two subjobs, as having a filename based on a column in your flow implies that this filename is extracted from another subjob.
You should have a first subjob getting the value of your column named TYPE into into a context variable
TDBInput->tJavaRow
TDBInput : just extract distinct TYPE column from your DB with a select query
tJavaRow : as you'll have only one row in the output, you can affect this value to a context variable : context.myVar=input_row.myColumn;
Then connect this first subjob to the second one (tDatabaseInput -> tMap -> tOutputDelimited)
, and use this context variable in your tFileOutputDelimited, in the filename field
"/path/"+context.myVar+".ext"

Related

How to update a jsonb column with a replaced value in pgAdmin?

I have a PostgreSQL table called files which includes a jsonb table called formats. While some rows are [null], others have objects with this structure:
{
"thumbnail": {
"ext": ".jpg",
"url": "https://some-url.com/image01.jpg",
"name": "image01.jpg",
//...other properties
}
}
For every row I want to update the thumbnail.url and replace some-url with other-url.
I'm far from being an expert in PostgreSQL (or any other DB for that matter), and after some reading I tried to run the following query in pgAdmin:
UPDATE files
SET formats = jsonb_set(formats, '{thumbnail.url}', REPLACE('{thumbnail.url}', 'some-url', 'other-url'))
And I received this error: function jsonb_set(jsonb, unknown, text) does not exist
I tried to set format jsonb_set(formats::jsonb...), tried to target '{thumbnail}' instead of '{thumbnail.url}' - always the same error.
What am I doing wrong? Or is pgAdmin really doesn't support this function? How can I do such an update with pgAdmin query tool?
We can try to use ->> to get JSON content value of url and then replace your expect value from that.
Because your url field of your JSON might be string type we need to use " to content it before cast as JSONB
jsonb_set(target jsonb, path text[], new_value jsonb [, create_missing boolean])
UPDATE files
SET formats = jsonb_set(formats, '{thumbnail,url}', CONCAT('"',REPLACE(formats->'thumbnail'->>'url','some-url','other-url'),'"')::JSONB);
sqlfiddle
The second parameter of jsonb_set() must be an array with one array element for each "path" element. So the second parameter should be '{thumbnail,url}' or more obvious: array['thumbnail', 'url']
And the third parameter must be a jsonb value, but replace returns a text, so you need to use e.g. to_jsonb() to convert the result of the replace() to a jsonb value.
And as D-Shih pointed out, you need to extract the old value using ->>. But to get the URL you need to "navigate" to it: formats -> 'thumbnail ->> 'url'
I would also add a WHERE clause so that you only update rows that actually contain a URL.
UPDATE files
SET formats = jsonb_set(formats,
'{thumbnail,url}',
to_jsonb(replace(formats -> 'thumbnail' ->> 'url', 'some-url', 'other-url'))
)
where (formats -> 'thumbnail') ? 'url'

What does `target` mean in `jsonb_set` of postgresql?

I am using jsonb type in a column in postgresql11. And I'd like to update one field in the json data and I see there is a function jsonb_set which can be used. (https://www.postgresql.org/docs/current/functions-json.html).
However, based on the document,
jsonb_set ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean ] ) → jsonb
Returns target with the item designated by path replaced by new_value, or with new_value added
if create_if_missing is true (which is the default) and the item designated by path does not
exist. All earlier steps in the path must exist, or the target is returned unchanged. As with
the path oriented operators, negative integers that appear in the path count from the end of
JSON arrays. If the last path step is an array index that is out of range, and create_if_missing
is true, the new value is added at the beginning of the array if the index is negative, or at
the end of the array if it is positive.
The first argument is target. What does target mean here? Do I need to do a query to get existing value and put it as target?
I have tried below update statement:
my current data is:
# select "taxes" from "Sites" where "id" = '6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
taxes
--------------------------------------------------------------------------------------------------------------
{"feePercent": 0, "percent": 0}
And I tried below update:
# update "Sites" set "feePercent" = jsonb_set('{"feePercent": 0, "percent": 0}', '{feePercent}', 1) where "siteUuid"='6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
but I got below error:
ERROR: function jsonb_set(unknown, unknown, integer) does not exist
LINE 1: update "Sites" set "feePercent" = jsonb_set('{"feePerce...
jsonb_set() modifies a specific JSON object. So, your target is the JSON object (or JSON column) which you want to modify.
jsonb_set(my_jsonb_to_be_modified, ...)
So, if you had this JSON object;
{"my":"old", "json":"object"}
With the function you can turn it into:
{"my":"new", "json":"object"}
The code is:
demo:db<>fiddle
SELECT jsonb_set('{"my":"old", "json":"object"}', '{my}', '"new"')
The target is the original JSON object, the path points to the element you want to modify, and new_value is the new value for the element you specified in the path.
In that case my had the value old, which turns into new now.
From PostgreSQL v14 on, you can use subscripts to make this UPDATE statement look natural:
UPDATE "Sites"
SET taxes['feePercent'] = to_jsonb(1)
WHERE id = '6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
For earlier versions, you will have to use jsonb_set like this:
UPDATE "Sites"
SET taxes = jsonb_set(taxes, ARRAY['feePercent'], to_jsonb(1))
WHERE id = '6daa9b5d-d5b2-4b0d-a8ee-5ad2cb141594';
The effect is the same: the whole JSON is read, a new JSON is created and stored in a new version of the row.
All this becomes much simpler if you don't use JSON, but regular table columns.

Updating JSONB object using another table

I am trying to update a JSONB field in one table with data from another table. For example,
update ms
set data = data || '{"COMMERCIAL": 3.4, "PCT" : medi_percent}'
from mix
where mix.id = mss.data_id
and data_id = 6000
and set_id = 20
This is giving me the following error -
Invalid input syntax for type json
DETAIL: Token "medi_percent" is invalid.
When I change medi_percent to a number, I don't get this error.
{"COMMERCIAL": 3.4, "PCT" : medi_percent} is not a valid JSON text. Notice there is no string interpolation happening here. You might be looking for
json_build_object('COMMERCIAL', 3.4, 'PCT', medi_percent)
instead where medi_percent is now an expression (that will presumably refer to your mix column).

How to insert new parameter into column in PostgreSql

I have a table called device, the table has a column called devicMeta. The deviceMeta looks like
{"id":"1234567890", "firmware":"1.001","hardware":"1.0"}
I want to insert a new parameter into column 'deviceMeta', for example "company":'ABC', the expected result is
{"id":"1234567890","firmware":"1.001","hardware":"1.0","company":'ABC'}
How can I do this using PostgreSql's UPDATE command
UPDATE "device"
?
WHERE "id" = '1234567890'
Assuming that column is defined as jsonb (which it should be) you can simply concatenate the new key/value pair:
update device
set devicemeta = devicemeta || '{"company": "ABC"}'
where id = 123456789;

Update column with multiple values Postgres

Sample data:
I am trying update a column with values from multiple columns in another table if two columns match.
Consider the following query:
UPDATE application_table
SET asset_list = asset_table.asset_name
FROM asset_table
WHERE application_table.application_name = asset_table.applications;
My table structure is:
application_table:
"asset_list"; "text[]"
"application_name"; "character varying"
asset_table:
"asset_name"; "character varying"
"applications"; "character varying"
I get the following error:
ERROR: column "asset_list" is of type text[] but expression is of type character varying
Line 12 SET asset_list = asset_table.asset_name
What you need to do is aggregate the asset_name per applications value and set asset_list to that aggregated value.
Problem is you can't do something like
UPDATE ..
SET asset_list = ARRAY_AGG(asset_name)
FROM ...
because aggregate functions are not allowed in updates like that.
So here's two other ways to do it:
UPDATE app_table
SET asset_list = _asset_list
FROM (
SELECT applications, ARRAY_AGG(asset_name ORDER BY asset_name) AS _asset_list
FROM asset_table
GROUP BY applications
) AS a
WHERE app_name = applications;
https://www.db-fiddle.com/f/pKB5k6Lexwzqv6ZbCCdJay/0
This first builds a result set of distinct application names and an array of all the asset_names for each of the app names. Then it updates the table as usual with that array value.
Another way is:
UPDATE app_table
SET asset_list = (SELECT ARRAY_AGG(asset_name ORDER BY asset_name)
FROM asset_table
WHERE applications = app_name)
;
https://www.db-fiddle.com/f/8oVWsubXW93n142gtZYLXB/0
This will update every record in app_table, and calculates the array value on the fly for every record.