How to put JSON into a column data if sub-query returns more than 1 row in MySQL How to put JSON into a column data if sub-query returns more than 1 row in MySQL database database

How to put JSON into a column data if sub-query returns more than 1 row in MySQL


A bit convoluted, but you could create JSON objects for each row, concatenate them using GROUP_CONCAT and cast the result (wrapped in [] to make it an array) to JSON;

SELECT u.uid, u.username,   CASE WHEN p.uid IS NULL        THEN NULL        ELSE CAST(CONCAT('[',                   GROUP_CONCAT(JSON_OBJECT('pid', p.pid,                                            'title', p.title,                                             'status', p.status)),                      ']') AS JSON) END portfoliosFROM user uLEFT JOIN portfolio p  ON u.uid=p.uidWHERE p.status = 1GROUP BY u.uid, u.username;

...which gives...

+------+----------+-----------------------------------------------------------------------------------------------------------------------------------------+|    1 | manoj    | [{"pid": 1, "title": "title 1", "status": 1}, {"pid": 2, "title": "title 2", "status": 1}, {"pid": 3, "title": "title 3", "status": 1}] ||    2 | testing  | [{"pid": 4, "title": "title 1", "status": 1}]                                                                                           ||    3 | user     | NULL                                                                                                                                    ||    4 | company  | NULL                                                                                                                                    |+------+----------+-----------------------------------------------------------------------------------------------------------------------------------------+

If you're using an older MySQL without JSON support, you could build it as a string;

SELECT u.uid, u.username,   CASE WHEN p.uid IS NULL  THEN NULL   ELSE CONCAT('[',     GROUP_CONCAT(CONCAT('{ "pid":',p.pid,',"title":"', REPLACE(p.title, '"', '\\"'),           '","status":',p.status, ' }')), ']') END portfoliosFROM user u LEFT JOIN portfolio p   ON u.uid=p.uid AND p.status=1GROUP BY u.uid, u.username;

...which will give you...

+------+----------+------------------------------------------------------------------------------------------------------------------------------+| uid  | username | portfolios                                                                                                                   |+------+----------+------------------------------------------------------------------------------------------------------------------------------+|    1 | manoj    | [{ "pid":2,"title":"title 2","status":1 },{ "pid":3,"title":"title 3","status":1 },{ "pid":1,"title":"title 1","status":1 }] ||    2 | testing  | [{ "pid":4,"title":"title 1","status":1 }]                                                                                   ||    3 | user     | NULL                                                                                                                         ||    4 | company  | NULL                                                                                                                         |+------+----------+------------------------------------------------------------------------------------------------------------------------------+


MySQL 8: With JSON_OBJECTAGG and JSON_OBJECT functions

SELECT     u.user_id,    u.username,    CASE WHEN p.user_id IS NULL        THEN NULL     ELSE         JSON_OBJECTAGG(            IF(p.portfolio_id IS NULL, '', p.portfolio_id ),             JSON_OBJECT('title', p.title, 'status', p.status)) END portfoliosFROM user AS uLEFT JOIN portfolio AS p ON u.user_id = p.user_id AND p.status = 1GROUP BY u.user_id;

Result:

+---------+----------+--------------------------------------------------------------------------------------------------------------------------+| user_id | username | portfolios                                                                                                               |+---------+----------+--------------------------------------------------------------------------------------------------------------------------+|       1 | manoj    | {"1": {"title": "title 1", "status": 1}, "2": {"title": "title 2", "status": 1}, "3": {"title": "title 3", "status": 1}} ||       2 | testing  | {"4": {"title": "title 1", "status": 1}}                                                                                 ||       3 | user     | NULL                                                                                                                     ||       4 | company  | NULL                                                                                                                     |+---------+----------+--------------------------------------------------------------------------------------------------------------------------+


as of 5.7 use

JSON_OBJECT('key1', 1, 'key2', 'abc');

Its way less complicated than multiple concat statements and has the same effect.