1

MySQL 5.7.24

Lets say I have 3 rows like this:

ID (PK) | Name (VARCHAR) | Data (JSON)
--------+----------------+-------------------------------------
 1      | Admad          | [{"label":"Color", "value":"Red"}, {"label":"Age", "value":40}]
 2      | Saleem         | [{"label":"Color", "value":"Green"}, {"label":"Age", "value":37}, {"label":"Hoby", "value":"Chess"}]
 3      | Daniel         | [{"label":"Food", "value":"Grape"}, {"label":"Age", "value":47}, {"label":"State", "value":"Sel"}]

Rule #1: The JSON column is dynamic. Means not everybody will have the same structure

Rule #2: Assuming I can't modify the data structure

My question, it it possible to query so that I can get the ID of records where the Age is >= 40? In this case 1 & 3.

Additional Info (after being pointed as duplicate): if you look at my data, the parent container is array. If I store my data like

{"Age":"40", "Color":"Red"} 

then I can simply use

Data->>'$.Age' >= 40

My current thinking is to use a stored procedure to loop the array but I hope I don't have to take that route. The second option is to use regex (which I also hope not). If you think "JSON search" is the solution, kindly point to me which one (or some sample for this noob of me). The documentation's too general for my specific needs.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Coisox
  • 1,002
  • 1
  • 10
  • 22
  • Possible duplicate of [How to search JSON data in MySQL?](https://stackoverflow.com/questions/30411210/how-to-search-json-data-in-mysql) – Raymond Nijland Mar 10 '19 at 14:45
  • Also see the JSON search functions in the [manual](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html) – Raymond Nijland Mar 10 '19 at 14:48
  • @RaymondNijland I don't think my question is similar to the one you pointed. If you look at my data, the parent container is array. If I store my data like {"Age":"40", "Color":"Red"} then I can simply use Data->>'$.Age' = 40 – Coisox Mar 10 '19 at 16:56
  • 1
    Why are you packing JSON into your database rather than using tables, columns and rows? – Lightness Races in Orbit Mar 10 '19 at 17:03
  • @LightnessRacesinOrbit I've got dynamic form fields where user can click "Add more fields". Using JSON make it much simpler than traditional way. I just need a good method to pick them again. – Coisox Mar 10 '19 at 18:17
  • 1
    Looks like it made things harder, not simpler. Don't cut corners; it'll _always_ bite you in the long run. – Lightness Races in Orbit Mar 10 '19 at 18:20
  • 1
    JSON makes it easier to INSERT the data, but it clearly makes it more complex to SELECT the data. You are making a tradeoff, and the fact that you couldn't figure out how to select your data without asking on Stack Overflow means it's not a good tradeoff. – Bill Karwin Mar 10 '19 at 18:26

1 Answers1

4

Here's a demo:

mysql> create table letsayi (id int primary key, name varchar(255), data json);

mysql> > insert into letsayi values
-> (1, 'Admad', '[{"label":"Color", "value":"Red"}, {"label":"Age", "value":"40"}]'),
-> (2, 'Saleem', '[{"label":"Color", "value":"Green"}, {"label":"Age", "value":"37"}, {"label":"Hoby", "value":"Chess"}]');

mysql>  select id, name from letsayi 
        where json_contains(data, '{"label":"Age","value":"40"}');
+----+-------+
| id | name  |
+----+-------+
|  1 | Admad |
+----+-------+

I have to say this is the least efficient way you could store your data. There's no way to use an index to search for your data, even if you use indexes on generated columns. You're not even storing the integer "40" as an integer — you're storing the numbers as strings, which makes them take more space.

Using JSON in MySQL when you don't need to is a bad idea.


Is it still possible to query age >= 40?

Not using JSON_CONTAINS(). That function is not like an inequality condition in a WHERE clause. It only matches exact equality of a subdocument.

To do an inequality, you'd have to upgrade to MySQL 8.0 and use JSON_TABLE(). I answered another question recently about that: MySQL nested JSON column search and extract sub JSON

In other words, you have to convert your JSON into a format as if you had stored it in traditional rows and columns. But you have to do this every time you query your data.

If you need to use conditions in the WHERE clause, you're better off not using JSON. It just makes your queries much too complex. Listen to this old advice about programming:

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian Kernighan


how people tackle dynamically added form fields

You could create a key/value table for the dynamic form fields:

CREATE TABLE keyvalue (
  user_id INT NOT NULL,
  label VARCHAR(64) NOT NULL,
  value VARCHAR(255) NOT NULL,
  PRIMARY KEY (user_id, label),
  INDEX (label)
);

Then you can add key/value pairs for each user's dynamic form entries:

INSERT INTO keyvalue (user_id, label, value)
VALUES (123, 'Color', 'Red'),
       (123, 'Age', '40');

This is still a bit inefficient in storage compared to real columns, because the label names are stored every time you enter a user's data, and you still store integers as strings. But if the users are really allowed to store any labels of their own choosing, you can't make those real columns.

With the key/value table, querying for age > 40 is simpler:

SELECT user_id FROM key_value
WHERE label = 'Age' AND value >= 40
Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • Thank you sir. I can make use of this answer. BTW, since you mention storing integer as string, I slightly modify my question. Is it still possible to query age >= 40? And when you said "Using JSON in MySQL when you don't", I just wondering how people tackle dynamically added form fields – Coisox Mar 10 '19 at 18:28
  • Also a problem is rounding issues with key/value table when storing decimals as strings..You could design/extend this key/value table to hold native types with more tables.. – Raymond Nijland Mar 10 '19 at 18:51
  • 1
    Or one `value` column for each SQL data type. – Bill Karwin Mar 10 '19 at 18:51
  • Since we tackle dynamic form fields with RDBMS, I can't find any use of the new JSON datatype. BTW, thx for the quote by Brian. – Coisox Mar 11 '19 at 02:25