Modify JSON array element - arrays

I have a table
id int | data json
With data:
1 | [1,2,3,2]
2 | [2,3,4]
I want to modify rows to delete array element (int) 2
Expected result:
1 | [1,3]
2 | [3,4]

As a_horse_with_no_name suggests in his comment the proper data type is int[] in this case. However, you can transform the json array to int[], use array_remove() and transform the result back to json:
with my_table(id, data) as (
values
(1, '[1,2,3,2]'::json),
(2, '[2,3,4]')
)
select id, to_json(array_remove(translate(data::text, '[]', '{}')::int[], 2))
from my_table;
id | to_json
----+---------
1 | [1,3]
2 | [3,4]
(2 rows)
Another possiblity is to unnest the arrays with json_array_elements(), eliminate unwanted elements and aggregate the result:
select id, json_agg(elem)
from (
select id, elem
from my_table,
lateral json_array_elements(data) elem
where elem::text::int <> 2
) s
group by 1;

Related

Hive query to print the collect_set value for multiple entries and not to print if the entry is once

My table in hive:
Group1 | sibling
=====================
ad3jkfk 4
ad3jkfk 4
ad3jkfk 2
fkjh43f 1
fkjh43f 8
fkjh43f 8
rjkhd93 7
rjkhd93 4
rjkhd93 7
abcd45 1
defg63 1
Expected result:
Group1 | sibling
===========================
ad3jkfk 4,4,2
fkjh43f 1,8,8
rjkhd93 7,4,7
collect_set produces an array of distinct values. For ad3jkfk it will produce 4,2, not 4,4,2
If you want 4,4,2, then use collect_list().
To filter arrays with more than 1 element, use size() function:
select Group1, concat_ws(',',sibling_list) sibling --Concatenate array to string delimited w comma like in your example
from
(
select Group1, collect_list(sibling) sibling_list --get the list
from mytable
group by Group1
)s
where size(sibling_list)>1 --filter

Finding the Difference By Row Between 2 Columns that are Both Arrays in SnowSql

I have a dataset that is comprised of a date and two other columns that are in array format. I am trying to find all the values in array_1 that are not in array_2.
Date | Array_1 | Array_2
-------------------------
1/20 | [1,2,3] | [1,2]
2/20 | [4,5,6] | [[1,2,4]
Desired Output:
Date | Array_1
--------------
1/20 | [3]
2/20 | [5,6]
The idea is:
Unnest ("flatten") the values into two tables.
Use set functions for the operation you want.
Re-aggregate to an array.
I don't have Snowflake on hand, but I think this is how it works:
select t.*, array_3
from t left join lateral
(select array_agg(el) as array_3
from (select array_1
from table(flatten(input ==> t.array_1)) a1
except
select array_2
from table(flatten(input ==> t.array_2)) a2
) x
) x
Just to remind that if you were to use application code for this, it might be as simple as (using PHP for this example):
$array1 = array(4,5,6);
$array2 = array(5,6,7);
print_r(array_diff($array1, $array2));
Outputs: Array ( [0] => 4 )

Count the number of overlapping elements in Postgres array

I have an array of integer as a column.
Is there a way to query the number of overlapping integers?
For example for the following 3 records:
COLUMN1
{1,3,7}
{3,4,5}
{1,2}
How can I get the number of overlapping elements with ARRAY[3,4,8] ?
The result for my example should be:
1 (element 3)
2 (element 3 and 4)
0 (none)
I've found
SELECT COLUMN1 && ARRAY[44,45,46] FROM table1
But that returns a true or false.
If you install the intarray extension you can use the "intersection" operator from that extension:
select column1, column1 & ARRAY[3,4,8] as elements
from table1
returns:
column1 | elements
--------+---------
{1,3,8} | {3,8}
{3,4,5} | {3,4}
{1,2} | {}
To get the number of the elements in the resulting array, use cardinality(column1 & ARRAY[3,4,8])

Is it possible to use json_populate_recordset in a subquery?

I have a json array with a couple of records, all of which have 3 fields lat, lon, v.
I would like to create a select subquery from this array to join with another query. The problem is that I cannot make the example in the PostgreSQL documentation work.
select * from json_populate_recordset(null::x, '[{"a":1,"b":2},{"a":3,"b":4}]')
Should result in:
a | b
---+---
1 | 2
3 | 4
But I only get ERROR: type "x" does not exist Position: 45
It is necessary to pass a composite type to json_populate_recordset whereas a column list is passed to json_to_recordset:
select *
from json_to_recordset('[{"a":1,"b":2},{"a":3,"b":4}]') x (a int, b int)
;
a | b
---+---
1 | 2
3 | 4

Postgres, find the min value of array column and get its position

Let us assume the following table: test
ids | l_ids | distance
-----------------+-----------
53 | {150,40} | {1.235, 2.265}
22 | {20,520} | {0.158, 0.568}
The positions of the two arrays (l_ids, distance) are dependent, meaning that
150 corresponds to 1.235,
40 corresponds to 2.265 and so on.
I want to get the min distance and the respective l_id. Therefore the result should be like this:
ids | l_ids | distance
----------------+-----------
53 | 150 | 1.235
22 | 20 | 0.158
By running this:
select l_ids, min(dist) as min_distance
from test, unnest(test.distance) dist
group by 1;
the result is:
l_ids | dist
------------+-----------
{150,40} | 1.235
{20,520} | 0.158
I want to get the position of the minimum value in the array of distance in order to get the respective id from the array of l_ids.
Any guideline? Thank you in advance
SELECT DISTINCT ON (ctid) l_ids, distance
FROM (SELECT ctid,
unnest(l_ids) AS l_ids,
unnest(distance) AS distance
FROM test
) q
ORDER BY ctid, distance;
l_ids | distance
-------+----------
150 | 1.235
20 | 0.158
(2 rows)
If ids are unique identiter, and you don't have repeated values in distance array, this should work:
SELECT a.* from
(SELECT ids, UNNEST(l_ids) AS l_ids, UNNEST (distance) AS distance FROM test) a
INNER JOIN (SELECT ids, MIN(distance) as mind FROM (
SELECT ids, UNNEST (distance) AS distance FROM test
) t
GROUP BY ids ) t
ON
a.ids = t.ids and a.distance = t.mind
From 9.4, you can use UNNEST()'s special ROWS FROM()-like syntax:
select distinct on (ids) ids, l_id, dist min_distance
from test, unnest(l_ids, test.distance) d(l_id, dist)
order by ids, dist
Otherwise, this is typical greatest-n-per-group query.

Resources