Query specific text inside json text data in MYSQL - php

I'd like to query from the reviewed_by table below where the "company" is "AAA" and "review" is "Need Review"
Here's mysql table :
+-----------+
| DATA_TYPE |
+-----------+
| text |
+-----------+
+-------------------------+
| reviewed_by |
+-------------------------+
|[{"company":"AAA","review":"OK","reviewed_at":"2021-01-26 08:59:26"}]|
|[{"company":"BBB","review":"OK","reviewed_at":"2021-01-26 08:59:26"}]|
|[{"company":"AAA","review":"Need Review","reviewed_at":"N\/A"}]|
+-------------------------+
Here's the #1 query i've tried :
SELECT * FROM `t_transaction`
WHERE `reviewed_by`
LIKE '%`"company":"AAA","review":"Need Review"`%'
Here's the #2 query i've tried :
SELECT * FROM `t_transaction`
WHERE `reviewed_by`
LIKE '%"company":"AAA","review":"Need Review"%'
ci3 query :
$like = ['reviewed_by','"company":"AAA","review":"Need Review"'];
$this->db->select('*')
->from('t_transacion')
->group_by('id')
->like($like[0],$like[1]);
The result i've got from those 2 queries was nothing,
How can i do this type of query (and also if using codeigniter 3) ?

MySql has some functions that allow you to do search over a json field. See documentation.
The reviewed_by column is a json array and you want to seach the first element of that array. Using the function JSON_EXTRACT you can extract data from the json field. In your case to get the json in the first position in the array so we execute JSON_EXTRACT(reviewed_by, '$[0]') which will return {"company":"...","review":"..","reviewed_at":"..."}. From the returned json we can call again the JSON_EXTRACT function to get a value given a key. If we select JSON_EXTRACT(JSON_EXTRACT(reviewed_by, '$[0]'), "$.company") this will return the company value from inside the json.
There are different ways to select what you want. I will give you two option and they have pros and cons. Take a look at this stackoverflow.
First approach using the where clause:
SELECT reviewed_by
FROM t_transaction
WHERE JSON_EXTRACT(JSON_EXTRACT(reviewed_by, '$[0]'), "$.company") = "AAA"
AND JSON_EXTRACT(JSON_EXTRACT(reviewed_by, '$[0]'), "$.review") = "Need Review";
Second approach using the having clause:
SELECT JSON_EXTRACT(reviewed_by, '$[0]') AS json
FROM t_transaction
HAVING json -> "$.company" = "AAA"
AND json -> "$.review" = "Need Review";

Related

how to search value in json array mysql

I saved some array value via JSON encode to some table recode.here is JSON value
category_id ---- ["2","3"]
and I need search query to search category_id.someone can explain to me how I do this
$search=$_GET['sq'];
$sql="SELECT * FROM table WHERE category_id =".$search;
Here how I got the correct query using JSON_SEARCH method
SELECT * FROMtableWHERE JSON_SEARCH(category_id, 'all', '%1%') IS NOT NULL

How do I append MYSQL JSON

I have the following in my database when I run SELECT type FROM office;
+--------------------------------------------------------+
| type |
+--------------------------------------------------------+
| a:2:{i:0;s:16:"Shared Workspace";i:1;s:9:"Workshops";} |
+--------------------------------------------------------+
How can I add an extra JSON value for another type of office. Basically I'd like it to add the type "Private Offices". So the value in my DB will then look like:
+-----------------------------------------------------------------------------------+
| type
+-----------------------------------------------------------------------------------+
| a:3:{i:0;s:16:"Shared Workspace";i:1;s:9:"Workshops";i:2;s:15:"Private Offices";} |
+-----------------------------------------------------------------------------------+
That's not JSON format. It looks like the output of PHP's serialize() function.
There's no SQL function to append values to serialized PHP data. You should fetch it into a PHP application, unserialize() it into a PHP array, then add data to the PHP array and update it back into the database.
Something like the following (some details have been omitted, like the WHERE conditions for the specific row you reference).
<?php
$pdo = new PDO(...);
$typeSerialized = $pdo->query("SELECT type FROM office WHERE ...")->fetchColumn();
$typeArray = unserialize($typeSerialized);
$typeArray[] = "Private Offices";
$typeSerialized = serialize($typeArray);
$stmt = $pdo->prepare("UPDATE office SET type = ? WHERE ...");
$stmt->execute([$typeSerialized]);

How to read geometry data type from MySQL database using PHP

I have a table in MySQL that stores polygons. I can read this back on the command line using the following query:
mysql> SELECT polygonid, AsText(thepolygon) FROM polygons;
+-----------+----------------------------------------------------------------------------------------------------------------+ | polygonid | AsText(thepolygon) |
+-----------+----------------------------------------------------------------------------------------------------------------+ | 1 | POLYGON((36.96318 127.002881,37.96318 127.002881,37.96318
128.002881,36.96318 128.002881,36.96318 127.002881)) | +-----------+----------------------------------------------------------------------------------------------------------------+ 1 row in set, 1 warning (0.02 sec)
When I try to read this in PHP using the same query, polygonid comes back correctly, but thepolygon comes back as empty:
$query = "SELECT polygonid, AsText(thepolygon) FROM polygons";
$result = mysqli_query($con, $query);
while ($row = mysqli_fetch_array($result)) {
var_dump($row['polygonid']);
var_dump($row['thepolygon']);
[...]
results in
string(1) "1" NULL
meaning that 'thepolygon' comes back as NULL, but the 'polygonid' comes back just fine.
If I change the query to
SELECT polygonid, thepolygon FROM polygons
then I do get back binary data:
string(1) "1" string(97)
"�t{I{B#�1�3/�_#�t{I�B#�1�3/�_#�t{I�B#��`#�t{I{B#��`#�t{I{B#�1�3/�_#"
string
It's almost as if astext() does not work.
What am I doing wrong?
Thanks for any input at all!
Looks like it might just be because you've not given the AsText() selection an alias which can be picked up from the PHP array.
If you print out $row you might be able to see that your array does not have a thepolygon key.
Have you tried this?
$query = "SELECT polygonid, AsText(thepolygon) AS thepolygon FROM polygons";
It works on the command line because you're just printing out whatever is selected in the query, but in PHP you're trying to print out array keys - i.e. the name of the fields selected. Your MySQL query does not select a field called thepolygon, so it doesn't exist in the array either.

MySQL 5.7+, JSON_SET value in nested path

For a recent development project, we're using MySQL 5.7, so we can take advantages of the latest JSON-functions...
I'm building an UPDATE-query, where an nested json-object should be inserted / added into the attributes-column, of type JSON, see query below.
UPDATE `table` SET `table`.`name` = 'Test',
`table`.`attributes` = JSON_SET(
`table`.`attributes`,
"$.test1", "Test 1",
"$.test2.test3", "Test 3"
)
When I execute this query, the attributes-field contains the data
{"test1": "Test 1"}
instead of the wanted
{"test1", "Test 1", "test2": {"test3", "Test 3"}}
Also tried to use JSON_MERGE, but when I execute it multiple times, it creates an JSON-object like
{"test1": ["Test 1", "Test 1", "Test 1"... etc.], "test2": {"test3": ["Test 3", "Test 3", "Test 3"... etc.]}}
So, JSON_SET isn't working when nodes don't exist? JSON_MERGE merges till infinity?
The keys used in the JSON-object can be defined by the user, so it's not possible to create an empty JSON-object for all possible keys. Do we really need to execute an JSON_CONTAINS / JSON_CONTAINS_PATH query before each UPDATE query to determine if we need to use JSON_SET or JSON_MERGE / JSON_APPEND?
We're looking for a way to have a query which always works, so when "$.test4.test5.test6" is given, it will extend the current JSON-object, adding the full path... How can this be done?
As of MySQL version 5.7.13, assuming you desire an end result of
{"test1": "Test 1", "test2": {"test3": "Test 3"}}
In your example the attributes column that is being updated is set to {"test1": "Test 1"}
Looking at your initial UPDATE query, we can see $.test2.test3 does not exist.
So it can not be set as
JSON_SET() Inserts or updates data in a JSON document and returns the
result. Returns NULL if any argument is NULL or path, if given, does
not locate an object.
Meaning MySQL can add $.test2, but since $.test2 is not an object, MySQL can not add on to $.test2.test3.
So you would need to define $.test2 as a json object by doing the following.
mysql> SELECT * FROM testing;
+----+---------------------+
| id | attributes |
+----+---------------------+
| 1 | {"test1": "Test 1"} |
+----+---------------------+
1 row in set (0.00 sec)
mysql> UPDATE testing
-> SET attributes = JSON_SET(
-> attributes,
-> "$.test1", "Test 1",
-> "$.test2", JSON_OBJECT("test3", "Test 3")
-> );
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM testing;
+----+---------------------------------------------------+
| id | attributes |
+----+---------------------------------------------------+
| 1 | {"test1": "Test 1", "test2": {"test3": "Test 3"}} |
+----+---------------------------------------------------+
1 row in set (0.00 sec)
So instead of relying on the MySQL dot notation, you would need to explicitly tell MySQL that the key exists as a JSON object.
This is similar to how PHP also defines non-existent object property values.
$a = (object) ['test1' => 'Test 1'];
$a->test2->test3 = 'Test 3';
//PHP Warning: Creating default object from empty value
To get rid of the error, you would need to first define $a->test2 as an object.
$a = (object) ['test1' => 'Test 1'];
$a->test2 = (object) ['test3' => 'Test 3'];
Alternatively you could test and create the objects prior to using the dot notation, to set the values. Though with larger datasets this may be undesirable.
mysql> UPDATE testing
-> SET attributes = JSON_SET(
-> attributes, "$.test2", IFNULL(attributes->'$.test2', JSON_OBJECT())
-> ),
-> attributes = JSON_SET(
-> attributes, "$.test4", IFNULL(attributes->'$.test4', JSON_OBJECT())
-> ),
-> attributes = JSON_SET(
-> attributes, "$.test4.test5", IFNULL(attributes->'$.test4.test5', JSON_OBJECT())
-> ),
-> attributes = JSON_SET(
-> attributes, "$.test2.test3", "Test 3"
-> );
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM testing;
+----+---------------------------------------------------------------------------+
| id | attributes |
+----+---------------------------------------------------------------------------+
| 1 | {"test1": "Test 1", "test2": {"test3": "Test 3"}, "test4": {"test5": {}}} |
+----+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
Though in either case if the original data is not provided the JSON_OBJECT function call will empty out the nested object's property value(s). But as you can see from the last JSON_SET query, $.test1 was not provided in the definition of attributes, and it remained intact, so those properties that are unmodified can be omitted from the query.
Now, as of MySQL version 5.7.22 the easiest way is to use JSON_MERGE_PATCH like this:
UPDATE `table` SET `attributes` =
JSON_MERGE_PATCH(`attributes`, '{"test2": {"test3": "Test 3"}, "test4": {"test5": {}}}')
which gives the expected result of {"test1": "Test 1", "test2": {"test3": "Test 3"}, "test4": {"test5": {}}} as in your example.
Fyrye, thanks for the awnser, appreciate it a lot! Because of the data hasn't a fixed structure and can be different for every single record, I needed a solution where I could generate a query which would automatically generate the total JSON-object in a single query.
I really like your solution using the JSON_SET(attributes, "$.test2", IFNULL(attributes->'$.test2',JSON_OBJECT())) method. Because I continued my search, I also figured out a solution myself using JSON_MERGE function.
When i'm executing an update, i'm using JSON_MERGE to merge an empty JSON-object onto the field in the database, for all keys with subnodes, so the're available in the JSON-field in the database and after that, using JSON_SET to update values. So the complete query looks like this:
UPDATE table SET
-> attributes = JSON_MERGE(
-> attributes, '{"test2": {}, "test4": {"test5": {}}}'),
-> attributes = JSON_SET(attributes, "$.test2.test3", "Test 3");
After executing this query, the result will look something like this:
mysql> SELECT * FROM testing;
+----+---------------------------------------------------------------------------+
| id | attributes |
+----+---------------------------------------------------------------------------+
| 1 | {"test1": "Test 1", "test2": {"test3": "Test 3"}, "test4": {"test5": {}}} |
+----+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
I don't know which method is better at this time, both work for now. Will do some speed tests in the future to check how they preform when 1 update 10.000 rows!
After searching everywhere like many of you I've found the best possible solution listed here: https://forums.mysql.com/read.php?20,647956,647969#msg-647969
From the site:
he nodes and subnodes, but doesn't contains any data...
So in above example, the object will be like:
{"nodes": {}}
When executing an update, i'm using JSON_MERGE to merge the empty JSON-object onto the field in the database, so all the nodes / subnodes are available in the JSON-field in te database and after that, using JSON_SET to update values. So the complete query looks like this:
UPDATE table SET attributes = JSON_MERGE(attributes, '{"nodes": {}'), attributes = JSON_SET(attributes, "$.nodes.node2", "Node 2")
For now, this is working.
But it's an weird workaround. Maybe this can be reviewed in previous MySQL versions, so JSON_SET also creates parent-nodes when subnodes are set ?

PHP function that returns the names of all columns in a certain table, as an array

I've tried this: http://be.php.net/manual/en/function.mysql-list-fields.php, but there's too much detail here.
What I'm looking for is a function that returns an array of strings. This array should only contain the names of all columns that a certain table has.
So for instance, if I have a table with these columns:
username | email | gender |age | married | number_of_children | street | province
I should get the same thing as if I did this:
$vars = array('username','email','gender','age','married','number_of_children','street','province');
Is there a PHP function already that can do this? Or shall I need some SQL statements of my own?
you could also do
$query = mysql_query("SELECT * FROM `table`");
$result = mysql_fetch_assoc($query);
$keys = array_keys($result);
$keys will now contain all of the column names because they were the array keys in the $result array.
Theres a MySQL Query, which returns the column names asa result set.
SHOW COLUMNS FROM tablename
I think there is no direct PHP function that will do what you want.
You can:
use that function discarding the unneeded results.
use a SQL query over the INFORMATION_SCHEMA
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'database' AND TABLE_NAME = 'table'
use the MySQL specific 'desc table' or 'show columns from table' SQL sentences

Categories