I have a table in MySQL with data in a column in the following format:
[{"type_id":1,"price":50},{"type_id":3,"price":60}]
I need to find out price of the item based on its id. For example, I need to find out price of an item with type_id = 3
I have tried:
select JSON_EXTRACT(JSONColumn, '$[*].price') as prices, JSON_EXTRACT(JSONColumn, '$[*].type_id') as quantities from Items where ItemId = 123
and json_contains(JSONColumn, '{"type_id" : 3}')
This is not working. Can someone specify the correct way of querying json data?
SELECT test.id, jsontable.price
FROM test
CROSS JOIN JSON_TABLE (test.val,
'$[*]' COLUMNS (type_id INT PATH '$.type_id',
price INT PATH '$.price')) jsontable
WHERE jsontable.type_id = 3;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=baa0a24a4bbf10ba30202c7156720018
Related
I got a table with below configurations
Table: jsontesttable Column : ArrayCol of type Medium Text Sample
value: [123,45,67,85,78]
I use the below query to select List of IDS except one of the selected IDs
/*query to select list of IDs from the column and remove unwanted columns from the selection */
SELECT hm.Id FROM jsontesttable tbl,
JSON_TABLE(ArrayCol, '$[*]' columns (Id int path '$')) AS hm
WHERE hm.Id NOT IN (67,85)
I used below query to get the JSON array back but its treating as string at present
/*Convert the IDs back to a JSON int array like [123,45,78] */
SELECT JSON_ARRAY(GROUP_CONCAT(hm.Id SEPARATOR ',')) AS IDs FROM jsontesttable tbl,
JSON_TABLE(ArrayCol, '$[*]' columns (Id int path '$')) AS hm
WHERE hm.Id NOT IN (67,85)
But its generating rows like this only Not really needed to have " in the beggining and end
//["123,45,78,88,9,3,53,6"] //["83,97"]
/*Update the ArrayCol , column as the new array without the removed values!
Perform this updation only if ArrayCol contains one of these IDs in thisc ase it is 67 & 85
*/
Can i write direct UPDATE query to modify the column without the IDs that needs to be removed like
[123,45,67,85,78] => [123,45,78] //2 IDs changed
[67,222,14] => [222,14] //Just 1 ID is changed
[83,85,97] => [83,97] //Just 1 ID is changed
[21,12,17,19] => [21,12,17,19] //No change
WITH
cte AS ( SELECT ArrayCol, ROW_NUMBER() OVER () rn
FROM jsontesttable )
SELECT rn, JSON_ARRAYAGG(hm.Id) AS IDs
FROM cte
CROSS JOIN JSON_TABLE(ArrayCol, '$[*]' columns (Id int path '$')) AS hm
WHERE hm.Id NOT IN (67,85)
GROUP BY rn
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=ce067ef12d9ed0d0ef1866e0a32d2a40
It's pretty difficult to pick a title, I'm sorry for that!
What I have for a database structure is the following columns:
pages
id (int)
url (string)
content (string)
created_at (timestamp)
groups
id (int)
related_page_ids (json)
domain_id (int)
created_at (timestamp)
What I want to achieve is to retrieve all groups by a selected domain ID and then retrieve all the related_pages with it. If I should write it in ugly PHP and MySQL:
$groups = SELECT * FROM groups WHERE domain_id = 1;
foreach($groups as $group){
$pages = SELECT * FROM pages WHERE IN id = implode($group['related_page_ids']);
}
I hope that you understand my goals with the ugly example.
If you have access to JSON_TABLE (MySQL 8 / MariaDB 10.6) it can be done with that in a single query:
SELECT * FROM pages
WHERE id IN (
SELECT * FROM JSON_TABLE(
(SELECT JSON_ARRAYAGG(related_page_ids) FROM groups WHERE domain_id=1),
'$[*][*]' columns(rel_id INTEGER path '$')) AS jt );
The column needs to actually be of type JSON (not varchar) for this to work.
I want to write an MySQL Query where I replace a JSON Array with Data from another Table.
I have got two Tables, "Reserved" and "Seats". Reserved contains one column "Seats", an JSON Array referring to the ID of the Table "Seats". Table Seats also contains a column "Name". I now want to basically replace the IDs in the JSON Data of the Seats column of the Reserved Table, with the name of the corresponding IDs stored in the Seats Table.
Is there a way to do this in an Mysql Query. I do not know how to pack a query result in a JSON Format and return it as a column
I already tried to utilize JSON_EXTRACT somehow : see test below.
SELECT * FROM `seats` WHERE ID = JSON_EXTRACT('["276", "277", "278"]','$.*')
Basically I want a Query like this:
SELECT *,
JSONCreate(SELECT name from `seats` WHERE seats.id IN JSON_EXTRACT(reserved.seats)) as name
FROM `reserved`
WHERE 1
You can use one of the following solutions.
solution using JSON_SEARCH and JSON_ARRAYAGG
SELECT r.seats, JSON_ARRAYAGG(s.name)
FROM reserved r JOIN seats s ON JSON_SEARCH(r.seats, 'one', CONVERT(s.id, CHAR(10))) IS NOT NULL
GROUP BY r.seats
solution using ... MEMBER OF () and JSON_ARRAYAGG
SELECT r.seats, JSON_ARRAYAGG(s.name)
FROM reserved r INNER JOIN seats s ON CONVERT(s.id, CHAR) MEMBER OF(r.seats)
GROUP BY r.seats
solution using JSON_CONTAINS and JSON_ARRAYAGG
SELECT r.seats, JSON_ARRAYAGG(s.name)
FROM reserved r INNER JOIN seats s ON JSON_CONTAINS(r.seats, JSON_QUOTE(CONVERT(s.id, CHAR))) = 1
GROUP BY r.seats
You can also use JSON_TABLE to solve this:
SELECT JSON_ARRAYAGG(IFNULL(s.name, ''))
FROM reserved r, JSON_TABLE(
r.seats,
"$[*]" COLUMNS (
id CHAR(50) PATH "$"
)
) AS rr LEFT JOIN seats s ON rr.id = s.id
GROUP BY r.seats
Note: You can use INNER JOIN to remove the empty values. Instead of GROUP BY r.seats you should use a id column.
demo on dbfiddle.uk
Please take a look at the following table:
I am building a search engine which returns card_id values, based on search of category_id and value_id values.
To better explain the search mechanism, imagine that we are trying to find a car (card_id) by supplying information what part (value_id) the car should has in every category (category_id).
In example, we may want to find a car (card_id), where category "Fuel Type" (category_id) has a value "Diesel" (value_id), and category "Gearbox" (category_id) has a value "Manual" (value_id).
My problem is that my knowledge is not sufficient to build a query, which will returns card_ids which contains more than one pair of category_id and value_id.
For example, if I want to search a car with diesel engine, I could build a query like this:
SELECT card_id FROM cars WHERE category_id=1 AND value_id=2
where category_id = 1 is a category "Fuel Type" and value_id = 2 is "Diesel".
My question is, how can I build a query, which will look for more category-value pairs? For example, I want to look for diesel cars with manual gearbox.
Any help will be very appreciated. Thank you in advance.
You can do this using aggregation and a having clause:
SELECT card_id
FROM cars
GROUP BY card_id
HAVING SUM(category_id = 1 AND value_id = 2) > 0 AND
SUM(category_id = 3 and value_id = 43) > 0;
Each condition in the having clause counts the number of rows that match a given condition. You can add as many conditions as you like. The first, for instance, says that there is at least one row where the category is 1 and the value is 2.
SQL Fiddle
Another approach is to create a user defined function that takes a table of attribute/value pairs and returns a table of matching cars. This has the advantage of allowing an arbitrary number of attribute/value pairs without resorting to dynamic SQL.
--Declare a "sample" table for proof of concept, replace this with your real data table
DECLARE #T TABLE(PID int, Attr Int, Val int)
--Populate the data table
INSERT INTO #T(PID , Attr , Val) VALUES (1,1,1), (1,3,5),(1,7,9),(2,1,2),(2,3,5),(2,7,9),(3,1,1),(3,3,5), (3,7,9)
--Declare this as a User Defined Table Type, the function would take this as an input
DECLARE #C TABLE(Attr Int, Val int)
--This would be populated by the code that calls the function
INSERT INTO #C (Attr , Val) VALUES (1,1),(7,9)
--The function (or stored procedure) body begins here
--Get a list of IDs for which there is not a requested attribute that doesn't have a matching value for that ID
SELECT DISTINCT PID
FROM #T as T
WHERE NOT EXISTS (SELECT C.ATTR FROM #C as C
WHERE NOT EXISTS (SELECT * FROM #T as I
WHERE I.Attr = C.Attr and I.Val = C.Val and I.PID = T.PID ))
I have the following doubt about this simple INNER JOIN query.
I have these two tables that have to be joined togheter:
The first table is named VulnerabilityFix and contains the following columns:
Id: int identity
FixName: varchar
Vendor: varchar
Title: varchar
Version: varchar
The second table is named VulnerabilityAlertDocument_VulnerabilityFix (this bind the previous table to another table, but this is not important at this time) and contains the following columns:
VulnerabilityAlertDocumentId: int
VulnerabilityFixId: int
Now, on my DB the VulnerabilityFix table contains only an empty record (this record have an id but all the other fields are empty\null), infact if I perform a select *, I obtain:
select * from VulnerabilityFix
Id FixName Vendor Title Version
1
Into the VulnerabilityAlertDocument_VulnerabilityFix I have something like this:
select * from VulnerabilityAlertDocument_VulnerabilityFix
VulnerabilityAlertDocumentId VulnerabilityFixId
78385 1
78386 1
....................................................
....................................................
....................................................
78398 1
Ok, so I want JOIN toghert these 2 table in in such a way that passing the value of the VulnerabilityAlertDocumentId field of the VulnerabilityAlertDocument_VulnerabilityFix table, I obtain all the related record in the VulnerabilityFix table.
So in this case I aspect to retrieve the previous only record that having an id (having a value equal to 1) and all the other fields are empty\null.
So my query is:
SELECT VF.* FROM VulnerabilityAlertDocument_VulnerabilityFix VAD_VF
INNER JOIN VulnerabilityFix VF ON VAD_VF.VulnerabilityAlertDocumentId = VF.Id
WHERE VAD_VF.VulnerabilityAlertDocumentId = 1
The problem is that when I execute this query I obtain an empty set of records and not the unique record that I expetc to obtain.
Why? What am I missing?
Tnx
I think your query should be more like:
SELECT VF.* FROM VulnerabilityAlertDocument_VulnerabilityFix VAD_VF
INNER JOIN VulnerabilityFix VF ON VAD_VF.VulnerabilityFixId = VF.Id
WHERE VAD_VF.VulnerabilityAlertDocumentId = 78385
That is, you are using the wrong column at your ON condition since VulnerabilityFixId seems to be the foreign key over VulnerabilityFix.Id and not VulnerabilityAlertDocumentId.
On the other hand, I can't see any VulnerabilityAlertDocument_VulnerabilityFix.VulnerabilityAlertDocumentId with value 1 in you data set (where condition)