Home > database >  Group by Id and by alias?
Group by Id and by alias?

Time:06-17

I have a table with repeated Ids and with a JSON data that represents an alias "players_level", I'm trying to group the Ids so I don't have duplicated Ids but the problem is that when grouping the Ids I can't get the row with the greater "players_level" alias, example I have this data:

id score players players_level
1 0 {} 0
16 1000 {"1": {"222": [], "1232": [], "2824": [], "33332": [], "66345": []}} 2
17 0 {"1": {}} 1
16 500 {"1": {"2824": ["148500"]}, "48": {"2890": []}} 3

And I'm trying to group the data like this:

id score players players_level
1 0 {} 0
17 0 {"1": {}} 1
16 500 {"1": {"2824": ["148500"]}, "48": {"2890": []}} 3

As you can see the row 2 disappeared because its players_level was 2 and the fourth one has level 3... but when trying to group using multiple techniques with SQL (Group By, Order By, Max...) I can't get the right row to output :(

Can anybody help me please? I have a fiddle link with the data example:
https://www.db-fiddle.com/f/sfQVa722kfkNw2JyRdQJZr/0

CodePudding user response:

You can use HAVING with a subselect with MAX

Schema (MySQL v5.7)

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
CREATE TABLE IF NOT EXISTS `test` (
  `id` int(6) unsigned NOT NULL,
  `score` int(6) unsigned NOT NULL,
  `players` varchar(200) NOT NULL
) DEFAULT CHARSET=utf8;
INSERT INTO `test` (`id`, `score`, `players`) VALUES
  ('1', 0, '{}'),
  ('16', 1000, '{"1": {"222": [], "1232": [], "2824": [], "33332": [], "66345": []}}'),
  ('17', 0, '{"1": {}}'),
  ('16', 500, '{"1": {"2824": ["148500"]}, "48": {"2890": []}}')

Query #1

SELECT t.id, t.score, t.players,
  (CASE
  WHEN (JSON_CONTAINS(JSON_EXTRACT(t.players, '$."1"."2824"'), '148500') = 1 OR JSON_CONTAINS(JSON_EXTRACT(t.players, '$."1"."2824"'), '"148500"') = 1) THEN 3
  WHEN JSON_CONTAINS(JSON_KEYS(JSON_EXTRACT(t.players, '$."1"')), '"2824"') = 1 THEN 2
  WHEN JSON_CONTAINS(JSON_KEYS(t.players), '"1"') = 1 THEN 1
  ELSE 0
  END) players_level
from test t  
HAVING (id,players_level) IN (SELECT t.id,
  MAX(CASE
  WHEN (JSON_CONTAINS(JSON_EXTRACT(t.players, '$."1"."2824"'), '148500') = 1 OR JSON_CONTAINS(JSON_EXTRACT(t.players, '$."1"."2824"'), '"148500"') = 1) THEN 3
  WHEN JSON_CONTAINS(JSON_KEYS(JSON_EXTRACT(t.players, '$."1"')), '"2824"') = 1 THEN 2
  WHEN JSON_CONTAINS(JSON_KEYS(t.players), '"1"') = 1 THEN 1
  ELSE 0
  END) players_level
from test t
GROUP BY t.id);
id score players players_level
1 0 {} 0
17 0 {"1": {}} 1
16 500 {"1": {"2824": ["148500"]}, "48": {"2890": []}} 3

View on DB Fiddle

  • Related