3

I have a simple JSON array:

_bb jsonb =

[
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  },
  {
    "so": "1",
    "mdl": "FlashSale",
    "pos": "Bottom"
  },
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  }
]

What I want to achieve:

[
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  },
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  },
  {
    "so": "1",
    "mdl": "FlashSale",
    "pos": "Bottom"
  }
]

I tried doing

Select _bb  into _test  ORDER BY _bb->>'pos' ASC  ;

What I achieve is all the pos = "Top" be the first in the JSON and all the "Bottom" to be last. Is there a way to achieve this in Postgres?

5
  • I dont understand how ORDER BY _bb->>'pos' ASC would help to change the array index - can you share the structure?.. also in your original jsonb, _bb[1] is equal to _bb[3] - right?.. so what you say you have achieved is what you want then - no? Commented Nov 2, 2017 at 9:21
  • stackoverflow.com/questions/4088532/custom-order-by-explanation This should do the trick. You just have to convert it to your case Commented Nov 2, 2017 at 9:22
  • @VaoTsun Yea its _bb[3], but i would like to change the sort orders by placing "Top" as the priority to be first before "bottom". I'm not really too sure on what the syntax is to achieve it. Commented Nov 2, 2017 at 9:23
  • alphabetically "bottom" is before "top" - are those two possible values or there can be more?.. Commented Nov 2, 2017 at 9:25
  • @VaoTsun there can be more like "Middle"... Commented Nov 2, 2017 at 9:27

1 Answer 1

3
with j(_bb) as (values('[
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  },
  {
    "so": "1",
    "mdl": "FlashSale",
    "pos": "Bottom"
  },
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  }
]'::jsonb))
, ord(o,v) as (values(1,'Top'),(2,'Bottom'))
, un as (select *,jsonb_array_elements(_bb) i from j)
select jsonb_agg(i order by o) from un
join ord on v=i->>'pos'
;

with result in:

[
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  },
  {
    "so": "1",
    "mdl": "Testing",
    "pos": "Top"
  },
  {
    "so": "1",
    "mdl": "FlashSale",
    "pos": "Bottom"
  }
]

needless to say you have to build order matrix for all values, eg:

, ord(o,v) as (values(1,'Top'),(2,'Middle'),(3,'Bottom'))

http://rextester.com/ZNDQ97753

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

5 Comments

Thank, but can you explain the first line " t=# with " im not too familiar with this syntax.
ah - t=# is just a psql prompt, with is CTE syntax
noob question but, who do I test this out in a Query? I'm getting a syntax error "at or near t" when I do.
@Pickles I updated the answer, leaving query with no psql prompts or other decortions
and added link to live demo

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.