简体   繁体   中英

How to optimize this SQL query to filter on a longtext/JSON field

I have a table with a column of type longtext that stores nutrient values in JSON format. Here's an example of what the data looks like:

[{"label":"N","value":0.1,"percent":10},{"label":"P","value":0.1,"percent":10},{"label":"K","value":0.1,"percent":10},{"label":"S","value":"","percent":""},{"label":"Ca","value":"","percent":""},{"label":"Mg","value":"","percent":""},{"label":"Zn","value":"","percent":""},{"label":"Mn","value":"","percent":""},{"label":"Cu","value":"","percent":""},{"label":"B","value":"","percent":""},{"label":"Al","value":"","percent":""},{"label":"Fe","value":"","percent":""},{"label":"Na","value":"","percent":""},{"label":"Mo","value":"","percent":""}]

Currently I'm pulling all records from the Db and then using a foreach to iterate through each record and filter out those that don't have N, P, and K with non-zero / empty string percent values.

foreach($record as $rec){
                $nutrients = json_decode($rec->nutrients);
                $nutrientTextArray = [];
                foreach($nutrients as $n){
                    if(in_array($n->label, ['N', 'P', 'K'])){
                        if($n->percent != ''){
                            $nutrientTextArray[] = $n->percent;
                        } else {
                            $nutrientTextArray[] = 0;
                        }
                    } else {
                        if($n->percent != ''){
                            $nutrientTextArray[] = $n->percent . $n->label;
                        }
                    }
                }

However, iterating through all nutrients for each record takes too long. I tried wildcard matching within the SQL query itself to filter, doing something like the following,

select * from products where nutrients like '%"label":"N"%"label":"P"%"label":"K"%';

but that doesn't take into account the non-zero / empty percent aspect.

How can I modify this query to only select records that have labels N, P, and K, where each of those nutrients all have non-zero / empty string percent values?

Normalise your DB
Well, not really the answer to your question, but an approach.
Due to your rather complex query you can split your json data into proper db data (normalise it) such as every field is being refelected in db. Then you could go for regular query with joining thoes tables together.

Hacky one
Other than that, the more "hacky" and maybe not so reliable approach: Change your JSON data such as "percent" is directly behint "label" in your string. Than you can query for that one as well in one long wildcard term. But be warned: You are then relying on your data structure for results which is something I would not advise in general.

Best, Bent

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM