Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query on value of array elements (PostgreSQL)

The following query:

select unnest(Table2.L) as X, unnest(Table1.O) 
from Table1, Table2 
where Table1.code = Table2.code 
order by X ;

produces the desired results. I would, however, like to exclude (unnested) rows which match some value. Adding a condition to the query, such as the following:

and unnest(Table2.L) != '-'

obviously does not work. Is this possible? How?

like image 524
SabreWolfy Avatar asked Jun 26 '12 20:06

SabreWolfy


People also ask

How do I query an array in PostgreSQL?

Using unnest() expands an array to multiple rows. The non-array columns get repeated for each row.

How do you check if a value is present in an array Postgres?

You can specify ANY function as a SELECT column or in WHERE clause. You can specify the array as a literal using round braces and single quotes ( e.g '{1, 2, 3}'), a column name with array data type, or even a subquery whose result is an array. The above statement will return t/f for True/False.

How do you query an array?

To query if the array field contains at least one element with the specified value, use the filter { <field>: <value> } where <value> is the element value. To specify conditions on the elements in the array field, use query operators in the query filter document: { <array field>: { <operator1>: <value1>, ... } }


2 Answers

If by unnest(Table2.L) != '-' you mean

throw out all the unnested elements that are '-'

then use a derived table and filter out the unnested values you don't want:

select *
from (
    select unnest(Table2.L) as X, unnest(Table1.O) 
    from Table1 join Table2 on Table1.code = Table2.code
) dt
where X != '-'
order by X ;

If you mean

ignore all rows from Table2 where L contains '-'

then you can use the @> operator to check if L contains a certain element:

select unnest(Table2.L) as X, unnest(Table1.O)
from Table1 join Table2 on Table1.code = Table2.code
where not Table1.L @> ARRAY['-']

or you could use ANY:

select unnest(Table2.L) as X, unnest(Table1.O)
from Table1 join Table2 on Table1.code = Table2.code
where not '-' = any(Table1.L)

And do yourself a favor by forgetting that implicit joins exist, always use explicit join conditions.

like image 144
mu is too short Avatar answered Oct 08 '22 04:10

mu is too short


Another way of doing it:

SELECT x, y
FROM  (SELECT code, unnest(l) AS x FROM table1) t1
JOIN  (SELECT code, unnest(o) AS y FROM table2) t2 USING (code)
WHERE  x <> '-'
ORDER  BY x;

May of may not be faster. Depends on how selective the WHERE clause is. Run a quick EXPLAIN ANYLYZE.

Note that I untangled table1 and table2, which are reversed in the example. If you are confused by all the clarity, try substituting x -> y in the WHERE and ORDER BY clause.

If you actually want to eliminate occurrences of - on both sides, add AND y <> '-' to the WHERE clause - making it symmetric (no cuonfusion possible).
I would also ORDER BY x, y, if x is not guaranteed to be unique, to make the sort order stable.

Demo on sqlfiddle.

like image 28
Erwin Brandstetter Avatar answered Oct 08 '22 04:10

Erwin Brandstetter