0

I have this demo query that starts from a list of "author + articles" values:

VALUES
('author1', ARRAY[('title1', 'content1'), ('title2', 'content2')]),
('author2', ARRAY[('title3', 'content3'), ('title4', 'content4')])

I'd like to convert this into the following data structure:

author title content
author1 title1  content1
author1  title2 content2
author2 title3  content3
author2 title4  content4

I've come this far:

WITH "raw_data" ("author", "articles") AS  (
    VALUES
        ('author1', ARRAY[('title1', 'content1'), ('title2', 'content2')]),
        ('author2', ARRAY[('title3', 'content3'), ('title4', 'content4')])
),
"articles" AS (
    SELECT "author", unnest("articles") AS "article" FROM "raw_data"
)
SELECT author, article FROM "articles";

But I get the following:

author article
author1 (title1, content1)
author1  (title2, content2)
author2 (title3, content3)
author2 (title4, content4)

And I need to find a way to convert the record (title2, content1) into 2 distinct columns.

Thank you all!

1 Answer 1

1

You may achieve this by creating a custom type for your record and casting to it.

See example below

Schema (PostgreSQL v13)


Query #1

create type article as (title text, contents text);

There are no results to be displayed.


Query #2

WITH "raw_data" ("author", "articles") AS  (
    VALUES
        ('author1', ARRAY[('title1', 'content1'), ('title2', 'content2')]),
        ('author2', ARRAY[('title3', 'content3'), ('title4', 'content4')])
),
"articles"  AS (
    SELECT "author", ((unnest("articles"))::text::article).* FROM "raw_data"
)
SELECT * FROM "articles";
author title contents
author1 title1 content1
author1 title2 content2
author2 title3 content3
author2 title4 content4

View on DB Fiddle

Just breaking down the expression ((unnest("articles"))::text::article).*

  1. (unnest("articles") - converts your array to rows
  2. ((unnest("articles"))::text - casts each record to text (unable to cast directly to article at this time)
  3. (unnest("articles"))::text::article - cast each record to your article type
  4. ((unnest("articles"))::text::article).* - expand or select all from your record to get both columns

Let me know if this works for you

Sign up to request clarification or add additional context in comments.

3 Comments

Follow up question @ggordon : do you have any idea how to achieve a similar result starting from a single JSON document? (I'm preparing a JSON on PostgreSQL lecture and I'm putting together a few use-cases that are normally overlooked in favor of multiple queries and application logic)
You may create another question with some sample data and expected results and share the link here so that I and other S/O users may take a look at it
Btw, this is the resulting tutorial thanks to your help: github.com/marcopeg/amazing-postgresql/tree/main/projects/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.