3

So, at the moment I have two columns in a table, one of which containing a JSON document, like so:

        CID:
        2
        Name:
        {"first" : "bob","1" : "william", "2" : "archebuster", "last" : "smith"}    

When I do a search on this column using:

  SELECT "CID", "Name"->>(json_object_keys("Name")) AS name FROM "Clients" WHERE 
  "Name"->>'first' LIKE 'bob' GROUP BY "CID";

I get:

  CID | name
--------------
  2   | bob
  2   | william
  2   | archebuster
  2   | smith

When really I want:

 CID | name
  2  | bob william archebuster smith

How would i go about doing this? I'm new to JSON in postgresql. I've tried string_agg and it wouldn't work, presumably because i'm working in a json column, despite the fact '->>' should type set the result to string

UPDATE:

enter image description here

5
  • No sure try array_agg("Name"->>(json_object_keys("Name"))) AS name Commented May 22, 2014 at 16:58
  • For array agg I get "set-valued function called in context that cannot accept a set". For string agg I get "Error: string_agg(text) does not exist " Commented May 22, 2014 at 17:03
  • Insert those values in a temp table and use array_agg on that. Commented May 22, 2014 at 17:04
  • Not entirely sure how to do that tbh, been trying to convert the thing to an array but run into the same problem, where each row is {bob} {william} etc Commented May 22, 2014 at 17:49
  • go here dba.stackexchange.com Commented May 22, 2014 at 18:08

1 Answer 1

4

First, you need to understand, if you include a set-returning function into the SELECT clause, you will create an implicit LATERAL CROSS JOIN.

Your query in reality looks like this:

SELECT "CID", "Name"->>"key" AS name
FROM "Clients"
CROSS JOIN LATERAL json_object_keys("Name") AS "foo"("key")
WHERE "Name"->>'first' LIKE 'bob'
GROUP BY "CID", "Name"->>"key"

If you really want to do that, you can apply an aggregate function here (possibly array_agg or string_agg).

SQLFiddle

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

3 Comments

Thank you for the explanation. Aggregate functions don't work on this though. It makes the database complain that a 'set-valued function call is called in context that cannot accept a set'
@user3512424 You're wrong, aggregate function will work on this translated example. i.e. array_agg("Name"->>"key") AS names. Your query makes a perfect example to not use set-returning functions in the SELECT clause, unless you're know exactly what you're doing.
I don't think I am. See the results in : imgur.com/8S4JAqq Oh, one second, i udnerstand what you're saying now.. will try again

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.