Update column with multiple values Postgres - postgresql

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.

Related

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;

Adding values to a newly inserted column in an existing table in PostgreSQL 9.3

created a table named "collegetable":
create table collegetable (stid integer primary key not null,stname
varchar(50),department varchar(10),dateofjoin date);
provided values for each column:collegetable data
inserted a new column in it named "cgpa" and tried to add values for this column in one shot using the code:
WITH col(stid, cgpa) as
( VALUES((1121,8.01),
(1131,7.12),
(1141,9.86))
)
UPDATE collegetable as colldata
SET cgpa = col.cgpa
FROM col
WHERE colldata.stid = col.stid;
and got error :
ERROR:operator does not exist:integer=record
LINE9:where colldata.stid=col.stid;
HINT:No operator matches the given name and arguement type.you might need to add explicit type casts.
pls help in solving.thanks in advance.
The with clause only defines the names of the columns, not the data types:
with col (stid, cgpa) as (
...
)
update ...;
For details see the tutorial and the full reference

Postgres Update Using Select Passing In Parent Variable

I need to update a few thousand rows in my Postgres table using the result of a array_agg and spatial lookup.
The query needs to take the geometry of the parent table, and return an array of the matching row IDs in the other table. It may return no IDs or potentially 2-3 IDs.
I've tried to use an UPDATE FROM but I can't seem to pass into the subquery the parent table geom column for the SELECT. I can't see any way of doing a JOIN between the 2 tables.
Here is what I currently have:
UPDATE lrc_wales_data.records
SET lrc_array = subquery.lrc_array
FROM (
SELECT array_agg(wales_lrcs.gid) AS lrc_array
FROM layers.wales_lrcs
WHERE st_dwithin(records.geom_poly, wales_lrcs.geom, 0)
) AS subquery
WHERE records.lrc = 'nrw';
The error I get is:
ERROR: invalid reference to FROM-clause entry for table "records"
LINE 7: WHERE st_dwithin(records.geom_poly, wales_lrcs.geom, 0)
Is this even possible?
Many thanks,
Steve
Realised there was no need to use SET FROM. I could just use a sub query directly in the SET:
UPDATE lrc_wales_data.records
SET lrc_array = (
SELECT array_agg(wales_lrcs.gid) AS lrc
FROM layers.wales_lrcs
WHERE st_dwithin(records.geom_poly, wales_lrcs.geom, 0)
)
WHERE records.lrc = 'nrw';

how to retrieve the column values which are aggregated(like count) using groupby column

I want to display the contents of the aggregated columns that is part of group by sql statement.
Example:
SELECT Shippers.ShipperName,COUNT(Orders.OrderID) AS NumberOfOrders FROM Orders
WHERE Orders.ShipperID=Shippers.ShipperID
GROUP BY ShipperName
In the above example the output gives me count as one of the result, whereas i need the aggregated orders.orderID actual values even. So say if one result count shows me 2. I need to know what are those two values which have been grouped. This result should be as another column in the same table.
try this with GROUP_CONCAT
SELECT Shippers.ShipperName,COUNT(Orders.OrderID) AS NumberOfOrders , array_agg(Orders.OrderID) as which_are_those FROM Orders
WHERE Orders.ShipperID=Shippers.ShipperID
GROUP BY ShipperName
array_agg returns an array, but you can CAST that to text and edit as needed (see clarifications, below).
Prior to version 8.4, you have to define it yourself prior to use:
CREATE AGGREGATE array_agg (anyelement)
(
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);
or simply this:
SELECT Shippers.ShipperName,COUNT(Orders.OrderID) AS NumberOfOrders , string_agg(Orders.OrderID, ',') as which_are_those FROM Orders
WHERE Orders.ShipperID=Shippers.ShipperID
GROUP BY ShipperName

Update columns based on subquery containing "select unnest" clause

I am attempting to update a boolean column in one table based upon the values in a second.
UPDATE channels
SET contains_photos = TRUE
WHERE id IN (SELECT unnest(ancestors)
FROM channel_tree WHERE id = 11329);
The channel_tree.ancestors column contains an array of channel IDs. The above is failing with the following error:
ERROR: cannot TRUNCATE "channel_tree" because it is being used by active queries in this session
The overriding goal is to set the contains_photos column to true for all ancestors of a given channel. Any one know how best to alleviate this error, or even an alternative solution?
No idea why your error says TRUNCATE. It sounds like you have a trigger or rule that is doing a truncate that we can't see.
Here's some alternative ways of doing that same query:
UPDATE channels
SET contains_photos = TRUE
WHERE id = ANY (SELECT ancestors
FROM channel_tree WHERE id = 11329);
Or with a join:
UPDATE channels
SET contains_photos = TRUE
FROM channel_tree
WHERE channels.id = ANY (channel_tree.ancestors)
AND channel_tree.id = 11329;