Get statistics from MySQL json rows [duplicate] - mysql

I have a json object which has list of products under a bill. I want to write a mysql function for it which reads the data from the json and iterates over it one by one and inserts the same data to product and bill tables.
Here is my json object
{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":paid,"product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
Here I have a mysql function which reads the data from the JSON
CREATE DEFINER=`mydb`#`%` FUNCTION `raiseOrder`(dataObject Json)
RETURNS bigint(11)
BEGIN
DECLARE billNo BIGINT(11) DEFAULT NULL;
DECLARE customerName VARCHAR(64);
DECLARE date datetime DEFAULT NOW();
DECLARE total Float(12,2);
DECLARE taxamt Float(12,2);
DECLARE fixedCharges Float(12,2);
DECLARE products json;
DECLARE productId bigint(15) DEFAULT NULL;
DECLARE categoryId bigint(11);
DECLARE cost float;
DECLARE categoryName varchar(64);
DECLARE quantity int default 0;
DECLARE supplierId bigint(11);
DECLARE supplierName varchar(128);
SET billNo = (SELECT JSON_EXTRACT(dataObject, "$.billNo"));
SET customerName = (SELECT JSON_EXTRACT(dataObject, "$.customerName"));
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
RETURN 1;
END
Now with these lines
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
I get the inner products json and the id of the 0th product. But I want a way to iterate over the array of the products.

You can use a WHILE loop in conjunction with JSON_LENGTH to achieve this:
DECLARE json, products, product VARCHAR(4000);
DECLARE i INT DEFAULT 0;
SELECT '{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":"paid","product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
' INTO json;
SELECT json->"$.product" INTO products;
WHILE i < JSON_LENGTH(products) DO
SELECT JSON_EXTRACT(products,CONCAT('$[',i,']')) INTO product;
SELECT product;
SELECT i + 1 INTO i;
END WHILE;
You'll probably need to do more than simply 'SELECT product' though ;-)
NOTE: MySQL JSON functions were added in 5.7.8 so you'll need to check your MySQL version first.

Extension to this answer, and if you want to loop through the keys of json object, you can do this via this way
declare _keys int default 0;
declare i int default 0;
declare _current_key varchar(50) default '';
select JSON_KEYS(product) into _keys;
while i < JSON_LENGTH(_keys) do
select json_extract(json_unquote(_keys), concat('$[', i, ']')) into _current_key;
set i = i + 1;
end while;

Related

What seems to be the error here in the below code?

Error Code: 2014 Commands out of sync; you can't run this command now
Platform- My SQL Workbench
DELIMITER//
DROP PROCEDURE IF EXISTS must_watch_movies;
CREATE PROCEDURE
must_watch_movies ()
BEGIN DECLARE mTitle
VARCHAR (45);
DECLARE mDistributor VARCHAR (45);
DECLARE mRelease datetime;
DECLARE result VARCHAR (1000);
DECLARE no_records INTEGER DEFAULT FALSE;
DECLARE cursor_movies CURSOR FOR
SELECT title, Distributor, year (release_date)
FROM movies WHERE gross > 200000000 ORDER BY title;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET SET no_records = TRUE;
OPEN cursor_movies;
WHILE no_records = FALSE DO
FETCH cursor_movies INTO mTitle, mDistributor, mRelease;
SET result =
CONCAT ("'", mTitle, "','" mDistributor, "','" mRelease, "|");
END WHILE;
CLOSE cursor_movies;
SELECT result AS "Output";
END//
DELIMITER;
CALL must_watch_movies();
The declared values match the datatypes for actual column values in the table.
like mTitle and title are the same type
You have some errors in your code
A double SET when you decalre a handler
You have to concat result if you want all movies.
The out put must be some what more complicated, but i leave that to you
CREATE TABLE movies (title varchar(10),Distributor varchar(19), release_date date,gross BIGINT)
INSERT INTO movies VALUES('text1','text2', NOW(),200000001),('text3','text4', NOW(),200000001),('text5','text6', NOW(),200000001)
CREATE PROCEDURE
must_watch_movies ()
BEGIN DECLARE mTitle
VARCHAR (45);
DECLARE mDistributor VARCHAR (45);
DECLARE mRelease INT;
DECLARE result VARCHAR (1000) DEFAULT "";
DECLARE no_records INTEGER DEFAULT FALSE;
DECLARE cursor_movies CURSOR FOR
SELECT title, Distributor, year (release_date)
FROM movies WHERE gross > 200000000 ORDER BY title;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_records = TRUE;
OPEN cursor_movies;
WHILE no_records = FALSE DO
FETCH cursor_movies INTO mTitle, mDistributor, mRelease;
SET result = CONCAT (result,"'", mTitle, "','", mDistributor, "','", mRelease, "|");
END WHILE;
CLOSE cursor_movies;
SELECT result AS "Output";
END
CALL must_watch_movies()
| Output |
| :--------------------------------------------------------------------------------------- |
| 'text1','text2','2021|'text3','text4','2021|'text5','text6','2021|'text5','text6','2021| |
✓
db<>fiddle here

Loop through JSON object in mysql function

I have a json object which has list of products under a bill. I want to write a mysql function for it which reads the data from the json and iterates over it one by one and inserts the same data to product and bill tables.
Here is my json object
{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":paid,"product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
Here I have a mysql function which reads the data from the JSON
CREATE DEFINER=`mydb`#`%` FUNCTION `raiseOrder`(dataObject Json)
RETURNS bigint(11)
BEGIN
DECLARE billNo BIGINT(11) DEFAULT NULL;
DECLARE customerName VARCHAR(64);
DECLARE date datetime DEFAULT NOW();
DECLARE total Float(12,2);
DECLARE taxamt Float(12,2);
DECLARE fixedCharges Float(12,2);
DECLARE products json;
DECLARE productId bigint(15) DEFAULT NULL;
DECLARE categoryId bigint(11);
DECLARE cost float;
DECLARE categoryName varchar(64);
DECLARE quantity int default 0;
DECLARE supplierId bigint(11);
DECLARE supplierName varchar(128);
SET billNo = (SELECT JSON_EXTRACT(dataObject, "$.billNo"));
SET customerName = (SELECT JSON_EXTRACT(dataObject, "$.customerName"));
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
RETURN 1;
END
Now with these lines
SET products = (SELECT JSON_EXTRACT(dataObject, "$.products"));
SET productId = (SELECT JSON_EXTRACT(products, "$[0].productId"));
I get the inner products json and the id of the 0th product. But I want a way to iterate over the array of the products.
You can use a WHILE loop in conjunction with JSON_LENGTH to achieve this:
DECLARE json, products, product VARCHAR(4000);
DECLARE i INT DEFAULT 0;
SELECT '{"billNo":16,"date":"2017-13-11 09:05:01","customerName":"Vikas","total":350.0,"fixedCharges":100,"taxAmount":25.78,"status":"paid","product":[{"productId":"MRR11","categoryId":72,"categoryName":"Parker Pen","cost":200,"quantity":2,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}},{"productId":"MRR12","categoryId":56,"categoryName":"Drawing Books","cost":150,"quantity":3,"log":{"supplierId":"725","supplierName":"Rihant General Stores"}}]}
' INTO json;
SELECT json->"$.product" INTO products;
WHILE i < JSON_LENGTH(products) DO
SELECT JSON_EXTRACT(products,CONCAT('$[',i,']')) INTO product;
SELECT product;
SELECT i + 1 INTO i;
END WHILE;
You'll probably need to do more than simply 'SELECT product' though ;-)
NOTE: MySQL JSON functions were added in 5.7.8 so you'll need to check your MySQL version first.
Extension to this answer, and if you want to loop through the keys of json object, you can do this via this way
declare _keys int default 0;
declare i int default 0;
declare _current_key varchar(50) default '';
select JSON_KEYS(product) into _keys;
while i < JSON_LENGTH(_keys) do
select json_extract(json_unquote(_keys), concat('$[', i, ']')) into _current_key;
set i = i + 1;
end while;

how to apply while loop for loop query in mysql

CREATE DEFINER=`root`#`localhost` PROCEDURE `test4`()
BEGIN
declare GroupArray text;
DECLARE i INT DEFAULT 0;
DECLARE loopcount INT DEFAULT 0;
declare GroupId varchar (5);
set GroupArray=(select group_concat(distinct groupId) from EventList_View);
SET loopcount = (SELECT LENGTH(GroupArray) -
LENGTH(REPLACE(GroupArray,',', '')));
select loopcount;
WHILE i <= loopcount DO
SET i = i + 1;
SET GroupId = (SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(GroupArray,
',', i),',', -1));
select GroupId;
END WHILE;
END
this is my query i am trying to apply while loop and i want get all groupId but GroupArray [1,2,3]i am getting value but in loop count i am getting 0 can any one please tell me where am doing wrong . why i am unable to get loop count null and why i am not getting value 1,2,3 for group

Not able to assign month,day and year into local variables in mysql stored procedure even though data is there

I have to extract day, month and year of a date into variable and then do some updation on table
Problem I am having is that though i am able to get the result set by the local fields alway appear null
Mysql query is
DECLARE ExistingRecordYear INT;
DECLARE ExistingRecordMonth INT;
DECLARE ExistingRecordDay INT;
DECLARE CountRecords SMALLINT;
SELECT COUNT(*) , ExistingRecordYear = YEAR(updatedon),
ExistingRecordMonth = MONTH(updatedon), ExistingRecordDay = DAY(updatedon)
FROM `transactions`
WHERE `issuer_id` = _issuer_id
AND `msisdn` = _msisdn ;
Though updatedon is not a nullable field and my count result is 1 but i am still seeing null in all three fields of month,year,and day
Please help me in it
In a select statement, you use := to assign variables, not =. In addition, you probably want your variables to have a prefix to distinguish them from columns. Something like:
DECLARE v_ExistingRecordYear INT;
DECLARE v_ExistingRecordMonth INT;
DECLARE v_ExistingRecordDay INT;
DECLARE v_CountRecords SMALLINT;
SELECT v_CountRecords := COUNT(*) , v_ExistingRecordYear := YEAR(updatedon),
v_ExistingRecordMonth := MONTH(updatedon), v_ExistingRecordDay := DAY(updatedon)
FROM `transactions`
WHERE `issuer_id` = _issuer_id AND `msisdn` = _msisdn ;

mysql cursor - select IDs in stament

It returns IDs as string, it returns only one row which it has first ID. "7,6,5" It returns only 7; How can we correct this problem?
CREATE DEFINER=`root`#`localhost`
PROCEDURE `GET_COMPANION`(IN paramEmployeeId INT)
BEGIN
DECLARE counter INTEGER DEFAULT 0;
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_companion varchar(100) DEFAULT "";
DECLARE v_companion_list varchar(100) DEFAULT "";
-- declare cursor for companion_id
DEClARE companion_cursor CURSOR FOR
SELECT companion_id FROM employee_has_companion ehc
WHERE ehc.employee_id = paramEmployeeId;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1;
OPEN companion_cursor;
get_companion: LOOP
FETCH companion_cursor INTO v_companion;
IF v_finished = 1 THEN
LEAVE get_companion;
END IF;
-- build companion list
SET v_companion_list = CONCAT(v_companion,",",v_companion_list);
END LOOP get_companion;
CLOSE companion_cursor;
SELECT * FROM companion co
LEFT JOIN citizenship ci
ON co.citizenship_id = ci.citizenship_id
WHERE co.companion_id IN( SUBSTRING(v_companion_list,
1,LENGTH(v_companion_list)-1));
END
You can use FIND_IN_SET(str,strlist) to check existence of a string in a list of comma separated values.
Change:
SELECT * FROM companion co
LEFT JOIN citizenship ci
ON co.citizenship_id = ci.citizenship_id
WHERE co.companion_id IN( SUBSTRING(v_companion_list,
1,LENGTH(v_companion_list)-1));
To:
SELECT * FROM companion co
LEFT JOIN citizenship ci
ON co.citizenship_id = ci.citizenship_id
WHERE FIND_IN_SET( co.companion_id, v_companion_list ) > 0;