I have 2 tables in mysql database as followed:
character_classes
table:
+--------+----------+
| id | name |
+--------+----------+
| CLA001 | assassin |
| CLA002 | knight |
| CLA003 | vanguard |
+--------+----------+
player_inventories
table:
+--------------+----------------------+
| player_id | character_class |
+--------------+----------------------+
| UID000000001 | ["CLA001"] |
| UID000000002 | ["CLA001", "CLA002"] |
| UID000000003 | ["CLA001", "CLA002", "CLA003"] |
+--------------+----------------------+
I am trying to join the player_inventories
tbl to “character_classesto get
character_class's names from
character_classes` table:
SELECT player_id, (SELECT CONCAT_WS(
', ',
(select name from character_classes where id = JSON_EXTRACT( character_class, '$[0]') ),
(select name from character_classes where id = JSON_EXTRACT( character_class, '$[1]') ),
(select name from character_classes where id = JSON_EXTRACT( character_class, '$[2]') )
) ) as character_class_name
from player_inventories;
But the issue is the number of json items in character_class
field at player_inventories
tbl is varied, it can be 1,2 or 3 or even more so I need to hard code the index, i.e $[0
], $[1]
and $[2]
to get its corresponding name.
Is there any way to improve that query so that I can get all character class’ names on the fly without hard coding the index?
3
Answers
The other way without hard-coding the index, you can extract all character class names from the player_inventories table by using the JSON_CONTAINS function with a subquery to match the character_classes table. The names should then be combined using GROUP_CONCAT into a single column. Use GROUP BY to group the results by player_id.
Don’t store the class data as a JSON . Create a many to many table that maps player ID to class ID, then you can use a JOIN in your query to retrieve all the class names with having to use an array index.
This also makes it much easier to query on the classes. Finding all the Wizards in a table is a much easier query than searching JSON arrays.
For example:
Query #1
View on DB Fiddle
Consider @Tangential’s answer, and if changing table structures isn’t an option, try this solution:
First convert JSON array into rows using
JSON_TABLE
, then useGROUP BY
and the aggregate functionGROUP_CONCAT
to get the expected output :Demo here