0

I have a table called diary which includes columns listed below:

| id | user_id | custom_foods       |
|----|---------|--------------------|
| 1  | 1       | {"56": 2, "42": 0} |
| 2  | 1       | {"19861": 1}       |
| 3  | 2       | {}                 |
| 4  | 3       | {"331": 0}         |

I would like to count how many diaries having custom_foods value(s) larger than 0 each user have. I don't care about the keys, since the keys can be any number in string.

The desired output is:

| user_id | count   |
|---------|---------|
| 1       | 2       |
| 2       | 0       |
| 3       | 0       |

I started with:

select *
from diary as d
join json_each_text(d.custom_foods) as e
on d.custom_foods != '{}'
where e.value > 0

I don't even know whether the syntax is correct. Now I am getting the error:

ERROR: function json_each_text(text) does not exist
LINE 3: join json_each_text(d.custom_foods) as e

HINT: No function matches the given name and argument types. You might need to add explicit type casts.

My using version is: psql (10.5 (Ubuntu 10.5-1.pgdg14.04+1), server 9.4.19). According to PostgreSQL 9.4.19 Documentation, that function should exist. I am so confused that I don't know how to proceed now.

Threads that I referred to:

Community
  • 1
  • 1
ytu
  • 1,822
  • 3
  • 19
  • 42

1 Answers1

0

Your custom_foods column is defined as text, so you should cast it to json before applying json_each_text. As json_each_text by default does not consider empty jsons, you may get the count as 0 for empty jsons from a separate CTE and do a UNION ALL

WITH empty AS
  ( SELECT DISTINCT user_id,
                    0 AS COUNT
   FROM diary
   WHERE custom_foods = '{}' )
SELECT user_id,
       count(CASE
                 WHEN VALUE::int > 0 THEN 1
             END)
FROM diary d,
     json_each_text(d.custom_foods::JSON)
GROUP BY user_id
 UNION ALL
   SELECT *
FROM empty
ORDER BY user_id;

Demo

Kaushik Nayak
  • 30,772
  • 5
  • 32
  • 45