Array of arrays in PostgreSQL
From a curiosity standpoint, does anyone know why these are not supported?
One generic answer is because arrays are intrinsically anti-relational. Removing repeating values is how you achieve 1st normal form. To have repeating groups of repeating groups seems quite insane from a relational theoretical standpoint.
In general, the relationally-correct thing to do is to extract a table for your repeating values. So if you modeled something like this:
CREATE TABLE users (
id integer primary key,
name varchar,
favorite_colors varchar[],
...
);
it would behoove you to redefine this relationally like so:
CREATE TABLE users (
id integer primary key,
name varchar,
...
);
CREATE TABLE favorite_colors (
user_id integer references users,
color varchar
);
Or even:
CREATE TABLE users (
id integer primary key,
name varchar,
...
);
CREATE TABLE colors (
color varchar primary key
);
CREATE TABLE favorite_colors (
user_id integer references users,
color varchar references colors,
primary key (user_id, color)
);
Hstore supports a lot of functions, many of which would make it easy to integrate it into a relational worldview. I think the simplest way to solve your problem would be to use the each
function to convert your hstore values into relations you can then use like a normal set of values. This is how you address having multiple values in other databases anyway: querying, and working with result sets.
postgres array of arrays to columns
unnest() for a regular multidimensional array has the problem, that it expands all elements of all dimensions, not only the first one. So, there is no way for these types to get this done.
A possible workaround is casting the array into a JSON array. For JSON arrays this is not a problem:
demo:db<>fiddle
SELECT
id,
elems ->> 0 AS col1,
elems ->> 1 AS col2,
elems ->> 2 AS col3
FROM
table_a,
json_array_elements(array_to_json(arr)) elems
json_array_elements()
expands the first dimension of the array, so the subarrays are moved into their one row. Afterwards simple get their elemens by their indexes.
The query above eliminates the NULL rows because of its comma notation (which, in fact, is the shortcut for INNER JOIN LATERAL
in this case). This can be avoided using an LEFT OUTER JOIN LATERAL
instead:
demo:db<>fiddle
SELECT
id,
elems ->> 0 AS col1,
elems ->> 1 AS col2,
elems ->> 2 AS col3
FROM
table_a
LEFT JOIN LATERAL
json_array_elements(array_to_json(arr)) elems ON TRUE
Unnesting an array of arrays, to a simple array in plpgsql
You can't cast the result of a set returning function to an array.
DO
$do$
DECLARE
nested varchar[][] := '{{a},{b},{c}}';
unnested varchar[];
BEGIN
unnested := array(select * from unnest(nested));
END
$do$;
Postgresql array of arrays is equal?
Order your arrays in ARRAY_AGG
, then you can use =
to compare them to your ordered array literal:
SELECT
things.id,
ARRAY_AGG(DISTINCT ARRAY[parts.id, coalesce(parts.color_id, things.default_color)
FROM things
JOIN parts_has_things ON parts_has_things.thing_id = things.id
JOIN parts ON parts.id = parts_has_things.part_id
HAVING
ARRAY_AGG(DISTINCT ARRAY[parts.id, coalesce(parts.color_id, things.default_color)] ORDER BY parts.color_id) = ARRAY[ARRAY[1,1],ARRAY[2,1],ARRAY[3,2]]::BIGINT[][]
PostgreSQL: Without using a function, how can nested arrays be compared?
Since there is no array_except
function or operator in PostgreSQL, you have to unpack the array in your query:
SELECT id,
CASE missing_categories
WHEN ARRAY[NULL]::text[]
THEN ARRAY[]::text[]
ELSE missing_categories
END
FROM (SELECT tab.id,
array_agg(arr.elem) AS missing_categories
FROM tab
LEFT JOIN LATERAL unnest(tab.categories_a) AS arr(elem)
ON NOT tab.categories_b @> arr.elem
GROUP BY tab.id) AS q;
The outer query only replaces an array with a NULL element that occurs because of the outer join with an empty array.
POSTGRESQL: Group the values as ARRAY of ARRAYS
Use ARRAY_AGG
, and perform a two-level aggregation. First, aggregation by system and quarter to generate a series of records containing arrays for each quarter. Then, aggregate a second time by system alone to generate a single array-of-arrays.
WITH cte AS (
SELECT
System,
ARRAY_AGG(Value1 ORDER BY NameYear) AS Val1,
ARRAY_AGG(Value2 ORDER BY NameYear) AS Val2
FROM yourTable
GROUP BY System, Quarter
)
SELECT
System,
ARRAY_AGG(Val1) AS Val1,
ARRAY_AGG(Val2) AS Val2
FROM cte
GROUP BY
System;
Demo
postgresql Aggregate arrays into a single array with union of all elements
Something like this should work:
with mytable as
(
select 1 as id, array[1, 2, 3, 4] as myarray
union all
select 1 as id, array[5, 6] as myarray
union all
select 1 as id, array[7, 8] as myarray
)
select
id,
array_agg(elements order by elements)
from mytable, unnest(myarray) as elements
group by id
There's some discussion about building the custom function here: Concatenate/merge array values during grouping/aggregation
Convert string to array of arrays in PostgreSQL
You can simply replace the brackets with braces, and you have the string representation of the array, which you can cast to the desired data type.
SELECT CAST (replace(
replace(
'[[1.1, 1], [2.2, 2]]', '[', '{'
), ']', '}'
) AS float[]
);
replace
-------------------
{{1.1,1},{2.2,2}}
(1 row)
Abelisto's version is even simpler:
SELECT translate('[[1.1, 1], [2.2, 2]]', '[]', '{}')::float[];
Here, ::
is the PostgreSQL shortcut for the standard CAST
syntax.
Related Topics
Using Bcp Utility to Export SQL Queries to a Text File
How to Find SQL Language Specification
Sqlite3 (Or General SQL) Retrieve Nth Row of a Query Result
SQL - Use a Reference of a Cte to Another Cte
Sql: Retrieve Only the Records Whose Value Has Changed
Using Variables for Asc and Desc in Order By
Caculate Point 50 Miles Away (North, 45% Ne, 45% Sw)
SQL Server 2005: How to Subtract 6 Month
Deferrable Check Constraint in Postgresql
How to Find Duplicate Consecutive Values in This Table
Xml Query() Works, Value() Requires Singleton Found Xdt:Untypedatomic
Native Insert Query in Hibernate + Spring Data
Ssrs - Keep a Table the Same Width When Hiding Columns Dynamically
Get the Id of Last Inserted Records
How to Find Duplicate Entries and Delete the Oldest Ones in SQL