How to select each value of array - arrays

Consider following case
Table : tab1
id serial primary key
arr int[]
Now I want to select each value of arr.
SELECT * FROM (SELECT arr FROM tab1) AS tab2
I need kind of iteration in array.
e.g.
id arr
-----------------------------
1 [1,2]
2 [5,6,8]
So I could get result as
arr val
-------------------------------
[1,2] 1
[1,2] 2
[5,6,8] 5
[5,6,8] 6
[5,6,8] 8

Use unnest() for that:
WITH array_data(id,arr) AS ( VALUES
(1,ARRAY[1,2]),
(2,ARRAY[5,6,8])
)
SELECT arr,unnest(arr) AS val
FROM array_data;

I don't know if I've got well but here you have all you need
select id,
unnest(arr),
array_to_string(arr,','),
array_length(arr, 1)
from array_data;

Related

Postgresql array sum

Given an array column in a table of a PostgreSQL database containing the following:
{{765,4},{767,3},{569,5},{567,3},{725,5}}
How could I calculate the sum of all second elements of each subarray,
i.e. 4+3+5+3+5
You can try using UNNEST which expands an array to a set of rows, and filtering by the row number:
SELECT *, (
SELECT SUM(v)
FROM UNNEST(array_column) WITH ORDINALITY a(v, n)
WHERE n % 2 = 0
) FROM your_table;
I was able to resolve my objective presented here by using jsonb array.
The jsonbArray [{"an": 4, "qid": 765}, {"an": 3, "qid": 767}, {"an": 5, "qid": 569}, {"an": 3, "qid": 567}, {"an": 5, "qid": 725}]
The query that accomplishes the objective:
WITH answers as (
SELECT
(jsonbArray -> 'an')::int as an,
(jsonbArray -> 'qid')::int as qid
FROM (
SELECT jsonb_array_elements(jsonbArray) AS jsonbArray
FROM user where id = 1
) AS s
group by qid, an
)
select sum(an) as score from answers where qid in (765,725)
Result:
score
9

Postgresql: Filter array by series

Is there any way to filter and array column by a series?
It's simpler to explain with an example.
Imagine I have this data:
table: data
id tag
1 {a,b,c,d}
2 {a,c,d,b}
3 {c,d,a,b}
4 {d,c,b,a}
5 {d,a,b,c}
6 {d,a,c,b}
Now I want to get all rows, which have ["a", "b"] in that order and no items in between:
SELECT id from data where tags ???? ["a", "b"]
That query should return: 1,3,5
UPDATE 1:
After taking a look to array_position and array_positionS: https://www.postgresql.org/docs/10/functions-array.html
I wrote this query:
select id
from data
where 'a' = ANY(tags)
and 'b' = ANY(tags)
and (array_position(tags, 'a') + 1) = any(array_positions(tags, 'b' ))
Which works as expected
UPDATE 2:
As #klin comment, this would produce wrong result if 'a' can appear multiple times, for example {a,a,b,c,d}. So this is a more generic answer
select *
from data
where 'a' = any(tags)
and 'b' = any(tags)
and (
array_position(tags, 'a') + 1 = any(array_positions(tags, 'b' ))
or array_position(tags, 'b') - 1 = any(array_positions(tags, 'a' )))
You can use a regular expression on the text representation of the arrays.
select *
from my_table
where tag::text ~ '[\{,]a,b[,\}]'
Db<>Fiddle.

Athena: how to get a value based on filtered index in array of structs

I have a S3 table(test) with a column(sample) in array of struct format.
[{index=1, value='A'}, {index=2, value='B'}, {index=3, value='F'}, ...]
I tried this query and it works:
SELECT
date,
MAX(case when s.index = 1 then s.value else NULL end) AS a1,
MAX(case when s.index = 3 then s.value else NULL end) as a2
FROM test,
UNNEST(sample) AS t(s)
group by date;
Is there any way I can do the same without using unnest (e.g using filter function)?
Use array functions to process the arrays:
SELECT
date,
MAX(array_max(transform(filter(sample, e -> e.index = 1), e -> e.value))) AS a1,
MAX(array_max(transform(filter(sample, e -> e.index = 3), e -> e.value))) AS a2,
FROM test
GROUP BY 1
filter selects the elements with the index you are after, transform extracts the value properties from the selected elements, and array_max returns the max value.

Array difference in postgresql

I have two arrays [1,2,3,4,7,6] and [2,3,7] in PostgreSQL which may have common elements. What I am trying to do is to exclude from the first array all the elements that are present in the second.
So far I have achieved the following:
SELECT array
(SELECT unnest(array[1, 2, 3, 4, 7, 6])
EXCEPT SELECT unnest(array[2, 3, 7]));
However, the ordering is not correct as the result is {4,6,1} instead of the desired {1,4,6}.
How can I fix this ?
I finally created a custom function with the following definition (taken from here) which resolved my issue:
create or replace function array_diff(array1 anyarray, array2 anyarray)
returns anyarray language sql immutable as $$
select coalesce(array_agg(elem), '{}')
from unnest(array1) elem
where elem <> all(array2)
$$;
I would use ORDINALITY option of UNNEST and put an ORDER BY in the array_agg function while converting it back to array. NOT EXISTS is preferred over except to make it simpler.
SELECT array_agg(e order by id)
FROM unnest( array[1, 2, 3, 4, 7, 6] ) with ordinality as s1(e,id)
WHERE not exists
(
SELECT 1 FROM unnest(array[2, 3, 7]) as s2(e)
where s2.e = s1.e
)
DEMO
More simple, NULL support, probably faster:
select array(
select v
from unnest(array[2,2,null,1,3,3,4,5,null]) with ordinality as t(v, pos)
where array_position(array[3,3,5,5], v) is null
order by pos
);
Result: {2,2,null,1,4,null}
Function array_diff() with tests.
Postgres is unfortunately lacking this functionality. In my case, what I really needed to do was to detect cases where the array difference was not empty. In that specific case you can do that with the #> operator which means "Does the first array contain the second?"
ARRAY[1,4,3] #> ARRAY[3,1,3] → t
See doc

Can't make a slice of a column of a 2d array "cannot use Sudoku[0:9][0] (type [9]int) as type []int in assignment"

I'm making a simple game of sudoku using slices of a 9x9 2d array. I'm still starting out with Golang and have some C++ experience. I keep getting the error message "cannot use Sudoku[0:9][0] (type [9]int) as type []int in assignment".
var row1 []int = Sudoku[0][0:9]
This line correctly took the values of the first row of the 2d array and placed them into the row1 slice, but using var col1 []int = Sudoku[0:9][0] results in the error message above. What can I do? Thanks in advance!
For example,
package main
import "fmt"
func main() {
var Sudoku [9][9]int
fmt.Println(Sudoku)
var row1 []int = Sudoku[0][0:9]
fmt.Println(row1)
var col1 []int = Sudoku[0:9][0]
fmt.Println(col1)
}
Playground: https://play.golang.org/p/Jk6sqqXR5VE
10:6: cannot use Sudoku[0:9][0] (type [9]int) as type []int in assignment
TLDR: In Go, array and slice are not exactly the same. You can't assign a slice variable to an array value.
Details:
We start with Sudoku [9][9]int variable is an array.
The valid line var row1 []int = Sudoku[0][0:9]:
Sudoku[0] returns the element at index 0 of Sudoku, which is an array [9]int. Let's say we call this temporary result temp
Then temp[0:9]returns a slice of elements between index 0 and 9 (exclusive) in temp. That's why you can assign that to a slice variable row1
Now the trouble line var col1 []int = Sudoku[0:9][0]. Based on the naming, I guess your intention is to return the first column from Sudoku array
? Unfortunately, this is what happens:
Sudoku[0:9] returns the slice of elements between index 0 and 9 (exclusive) of Sudoku. Because each element in Sudoku is an array, this temp value actually holds all the rows from Sudoku and of type [][9]int.
Now temp[0]returns the first element of temp, which actually is just the first row of Sudoku and of type array [9]int. Thus, Go will complain when you try to assign it to a variable of type []int (a slice)
So if Sudoku is a matrix of
1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2
...
9 9 9 9 9 9 9 9 9
Even if Go does not complain about typing, the returned value will be [1 1 1 1 1 1 1 1 1] and not [1 2 3 4 5 6 7 8 9]
var col1 []int = Sudoku[0:9][0] gets you an array, not a slice. You could either declare as var col1 [9]int = Sudoku[0:9][0] (or better: col1 := Sudoku[0:9][0]), or if you really want a slice: var col1Slice []int = col1[:] after getting col1.
In general, things would be much easier if your sudoku structure were a 2D slice instead of 2D array, then you'd be dealing with only slices.
Working example of all of these:
https://play.golang.org/p/LE8qwFSy1m_e

Resources