how to apply while loop for loop query in mysql - 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

Related

return null value in the JSON_EXTRACT

MyJsonArray
[{"ID":"D29","PersonID":"23616639"},{"ID":"D30","PersonID":"22629626"}]
and I want from sql Function set this array in to my Table but return null value in the variable and not set record in My database
my function:
DELIMITER $$
CREATE DEFINER=`toshiari`#`localhost` FUNCTION `setTitleRecords`(`Title` VARCHAR(166) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, `List` JSON) RETURNS int(4)
BEGIN
DECLARE Item INT;
DECLARE HolderLENGTH INT;
DECLARE ValidJson INT;
DECLARE ID VARCHAR(166);
DECLARE PersonID VARCHAR(166);
DECLARE S1 VARCHAR(166);
DECLARE S2 VARCHAR(166);
SET ValidJson = (SELECT JSON_VALID(List));
IF ValidJson = 1 THEN
SET HolderLENGTH = (SELECT JSON_LENGTH(List));
SET Item = 0;
WHILE Item < HolderLENGTH DO
SET S1 = CONCAT("'$[",Item, "].ID'");
SET S2 = CONCAT("'$[",Item, "].PersonID'");
SET ID = (SELECT JSON_EXTRACT(List,S1));
SET PersonID = (SELECT JSON_EXTRACT(List,S2));
INSERT INTO `Titles`(`ID`,`PersonID`,`Title`) VALUES (ID, PersonID, Title);
SET Item = Item + 1;
END WHILE;
RETURN 3;
ELSE
RETURN 2;
END IF;
END$$
DELIMITER ;
when I use this command in the Sql commands no problem and return true value
SELECT JSON_EXTRACT('[{"ID":"D29","PersonID":"23616639"},{"ID":"D30","PersonID":"22629626"}]','$[0].ID') return "D29"
return
"D29"
but in when run function from this code
return error and said:
SET #p0='DR'; SET #p1='[{\"ID\":\"D29\",\"PersonID\":\"23616639\"},{\"ID\":\"D30\",\"PersonID\":\"22629626\"}]'; SELECT `setTitleRecords`(#p0, #p1) AS `setTitleRecords`;
#4042 - Syntax error in JSON path in argument 2 to function 'json_extract' at position 1
I created a little test, in order to reproduce your issues. Basically you just need to redeclare S1 and S2, in the following way:
SET S1 = CONCAT('$[',Item,'].ID');
SET S2 = CONCAT('$[',Item,'].PersonID');
And that's it. You can check the test in the following url: https://www.db-fiddle.com/f/2TPgF868snjwcHN3uwoSEA/0

MySQL If Statement and Increment

I am having issues with a MySQL If statement that creates a group rank. here is the MySQL Statement:
SELECT EnCode, EnName, QuScore,
#scorerank := IF(#currathlete = EnCode, #scorerank + 1, 1),
#currathlete := EnCode
FROM ranking ORDER BY EnCode, QuScore DESC
It currently gives the following output
'1004277','Ashe','1628','1','1004277'
'1004277','Ashe','1309','1','1004277'
'1004277','Ashe','1263','1','1004277'
'1004277','Ashe','648','1','1004277'
'1004277','Ashe','645','1','1004277'
'1004277','Ashe','1628','1','1004277'
'1015934', 'Sabina', '544', '1', '1015934'
'1015934', 'Sabina', '455', '1', '1015934'
'1015934', 'Sabina', '276', '1', '1015934'
'1015934', 'Sabina', '216', '1', '1015934'
What it should be doing is incrementing each of the '1' numbers by one for each row that has the same code, and then starting from 1 again when it sees a different code number (1004277, then 1015934 in this case)
Any help is appreciated as i have followed a number of examples online using the above method but seem to hit the same issue a this point.
Try this way in stored Procedure:
drop PROCEDURE if EXISTS INCREMENTME;
create PROCEDURE INCREMENTME()
BEGIN
DECLARE OldEnNamevar VARCHAR(10) DEFAULT NULL;
DECLARE done INT DEFAULT FALSE;
DECLARE Encodevar VARCHAR(10);
DECLARE EnNamevar VARCHAR(10);
DECLARE QuScorevar VARCHAR(10);
DECLARE scorerankvar VARCHAR(10);
DECLARE currathalthletevar VARCHAR(10);
DECLARE countcode int(29) DEFAULT(1);
DECLARE counter int(20) default 0;
DECLARE get_cur CURSOR FOR select `Encode`,`EnName`,`QuScore`,`scorerank`,`currathalthlete` from tbl_ranking;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
drop table if exists temp_temptable;
create TEMPORARY table temp_temptable(Encodevar VARCHAR(50) NULL,EnNamevar VARCHAR(50) NULL,QuScorevar VARCHAR(50) NULL,scorerankvar VARCHAR(50) NULL,currathalthletevar VARCHAR(50) NULL,recordCount int(10) null);
OPEN get_cur;
REPEAT
set counter = counter + 1;
FETCH get_cur INTO Encodevar,EnNamevar,QuScorevar,scorerankvar,currathalthletevar;
if (OldEnNamevar = EnNamevar) THEN
set countcode = countcode +1;
ELSE
if(counter=1) then
set countcode = 1;
ELSE
set countcode = 0;
end if;
end if;
if (OldEnNamevar != EnNamevar) THEN
set countcode = 1;
end if;
if(OldEnNamevar=NULL) then
set countcode = 1;
end if;
insert into temp_temptable (Encodevar,EnNamevar,QuScorevar,scorerankvar,currathalthletevar,recordCount) values(Encodevar,EnNamevar,QuScorevar,scorerankvar,currathalthletevar,countcode);
set OldEnNamevar = EnNamevar;
UNTIL done END REPEAT;
select * from temp_temptable;
drop temporary table if exists temp_temptable;
CLOSE get_cur;
END
call the procedure like this:
call INCREMENTME();
Here's the result:
You have to initialize your variables, otherwise they are null (at least at the beginning of the session, probably not anymore if you run it twice), and your query will give strange results. Try
SELECT EnCode, EnName, QuScore,
#scorerank := IF(#currathlete = EnCode, #scorerank + 1, 1),
#currathlete := EnCode
FROM ranking, (select #currathlete := '', #scorerank := 0) init
ORDER BY EnCode, QuScore DESC

Mysql stored procedure cant get the id of the object

CREATE DEFINER=`root`#`localhost` PROCEDURE `add_card`(author VARCHAR(50),newtext VARCHAR(600),title VARCHAR(200),newSource VARCHAR(2300), username VARCHAR(50), tags VARCHAR(600))
BEGIN
DECLARE strLen INT DEFAULT 0;
DECLARE SubStrLen INT DEFAULT 0;
DECLARE cardId INT DEFAULT 0;
DECLARE tagId INT DEFAULT 0;
DECLARE tempTagId INT DEFAULT -1;
DECLARE temp VARCHAR(200);
INSERT INTO cards (author,text,title,username,source) VALUES (author,newtext,title,username,newSource);
SET #cardId = LAST_INSERT_ID();
Select #cardId;
IF tags IS NULL THEN
SET tags = '';
END IF;
do_this:
LOOP
SET strLen = CHAR_LENGTH(tags);
SET #temp = SUBSTRING_INDEX(tags, ',', 1);
SELECT tagId INTO tempTagId FROM tag WHERE tagName = #temp limit 1;
Select tempTagId;
SELECT tagId FROM tag WHERE tagName = 'ss';
IF tempTagId = -1 THEN
INSERT INTO tag (tagName) VALUES (#temp);
SET #tagId = LAST_INSERT_ID();
select #tagId+10;
IF NOT EXISTS (SELECT * FROM cards_tags WHERE tagId = #tagId AND cardId = #cardId) THEN
INSERT INTO cards_tags (tagId,cardId) VALUES (#tagId,#cardId);
Select #cardId;
END IF;
ELSE
IF NOT EXISTS (SELECT * FROM cards_tags WHERE tagId = tempTagId AND cardId = #cardId) THEN
INSERT INTO cards_tags (tagId,cardId) VALUES (tempTagId,#cardId);
select #tagId;
END IF;
END IF;
SET SubStrLen = CHAR_LENGTH(SUBSTRING_INDEX(tags, ',', 1)) + 2;
SET tags = MID(tags, SubStrLen, strLen);
IF tags = '' THEN
LEAVE do_this;
END IF;
END LOOP do_this;
END
It is the damnest thing i have ever seen i guess. I have this stored procedure and in the line
SELECT tagId FROM tag WHERE tagName = 'ss';
I am trying to get the id of the object but it is returning 0.
created another stored procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `adds_card`()
BEGIN
DECLARE temp VARCHAR(200);
SET #temp ='ss';
SELECT tagId FROM tag WHERE tagName = #temp;
END
And this returns 3 which is true. Why is the first one returning 0? Driving me really crazy. Spent 5 hours on it and couldnt solve it.
One line in your code is:
SELECT tagId INTO tempTagId FROM tag WHERE tagName = #temp limit 1;
#temp is not defined anywhere, although temp is. So, #temp defaults to NULL (or to the previous session value) and the WHERE clause likely fails.
I strongly recommend prepending local variables with a prefix, so they are not confused with column names. So I would recommend:
SELECT tagId INTO v_tempTagIdFROM tag WHERE tagName = v_temp limit 1;
or:
SELECT v_tempTagIdFROM := tagId
FROM tag
WHERE tagName = v_temp
LIMIT 1;

no return value of call procedure mysql

I have a procedure in mysql and it has 4 parameters as Input and 3 parameters of OUTPUT and one param of OUTPUT doesn't return nothing (null).
DELIMITER $$
drop procedure if exists `cierreMes`$$
create procedure cierreMes (in tarjeta varchar(100),in bancoBus varchar(100),in mes int,in anyo int, out total int, out nulas int, out erroneas int)
begin
declare stockActual int default 0;
declare cantidad int;
/*declare xcantidad,xnulas,xerroneas int;*/
declare entrada, salida int default 0;
declare total int default 0;
select stock
into stockActual
from almacen
where idProducto =
(select idProducto from productos where productos.banco = bancoBus and productos.plastico = tarjeta);
call entradasSalidas(tarjeta,bancoBus,mes,anyo,#ent,#sal);
set entrada = #ent;
set salida = #sal;
call obtenerMovimientosMes(tarjeta,bancoBus,mes,anyo,#cant,#nul,#err);
set cantidad = #cant;
set nulas = #nul;
set erroneas = #err;
set total =(stockActual + entrada) - (salida + cantidad);
select total;
end$$
DELIMITER ;
call cierreMes('4B MC','SANTANDER',3,2013, #total, #nulas, #erroneas);
select #total, #nulas, #erroneas;
When i do "call" #nulas and #erroneas return a value, but #total
nothing.
With select total, its works fine. but no returns a value, in this select : select #total, #nulas, #erroneas; #total is null.
You calculate total with this formula:
set total =(stockActual + entrada) - (salida + cantidad);
If one of the values used in the calculation is NULL, then total will be NULL.
I can see set statements for entrada, salida, and cantidad. But what is the value of stockActual?
It seems you are missing a statement that will set the value of stockActual.

T-SQL: split and aggregate comma-separated values

I have the following table with each row having comma-separated values:
ID
-----------------------------------------------------------------------------
10031,10042
10064,10023,10060,10065,10003,10011,10009,10012,10027,10004,10037,10039
10009
20011,10027,10032,10063,10023,10033,20060,10012,10020,10031,10011,20036,10041
I need to get a count for each ID (a groupby).
I am just trying to avoid cursor implementation and stumped on how to do this without cursors.
Any Help would be appreciated !
You will want to use a split function:
create FUNCTION [dbo].[Split](#String varchar(MAX), #Delimiter char(1))
returns #temptable TABLE (items varchar(MAX))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end;
And then you can query the data in the following manner:
select items, count(items)
from table1 t1
cross apply dbo.split(t1.id, ',')
group by items
See SQL Fiddle With Demo
Well, the solution i always use, and probably there might be a better way, is to use a function that will split everything. No use for cursors, just a while loop.
if OBJECT_ID('splitValueByDelimiter') is not null
begin
drop function splitValueByDelimiter
end
go
create function splitValueByDelimiter (
#inputValue varchar(max)
, #delimiter varchar(1)
)
returns #results table (value varchar(max))
as
begin
declare #delimeterIndex int
, #tempValue varchar(max)
set #delimeterIndex = 1
while #delimeterIndex > 0 and len(isnull(#inputValue, '')) > 0
begin
set #delimeterIndex = charindex(#delimiter, #inputValue)
if #delimeterIndex > 0
set #tempValue = left(#inputValue, #delimeterIndex - 1)
else
set #tempValue = #inputValue
if(len(#tempValue)>0)
begin
insert
into #results
select #tempValue
end
set #inputValue = right(#inputValue, len(#inputValue) - #delimeterIndex)
end
return
end
After that you can call the output like this :
if object_id('test') is not null
begin
drop table test
end
go
create table test (
Id varchar(max)
)
insert
into test
select '10031,10042'
union all select '10064,10023,10060,10065,10003,10011,10009,10012,10027,10004,10037,10039'
union all select '10009'
union all select '20011,10027,10032,10063,10023,10033,20060,10012,10020,10031,10011,20036,10041'
select value
from test
cross apply splitValueByDelimiter(Id, ',')
Hope it helps, although i am still looping through everything
After reiterating the comment above about NOT putting multiple values into a single column (Use a separate child table with one value per row!),
Nevertheless, one possible approach: use a UDF to convert delimited string to a table. Once all the values have been converted to tables, combine all the tables into one table and do a group By on that table.
Create Function dbo.ParseTextString (#S Text, #delim VarChar(5))
Returns #tOut Table
(ValNum Integer Identity Primary Key,
sVal VarChar(8000))
As
Begin
Declare #dlLen TinyInt -- Length of delimiter
Declare #wind VarChar(8000) -- Will Contain Window into text string
Declare #winLen Integer -- Length of Window
Declare #isLastWin TinyInt -- Boolean to indicate processing Last Window
Declare #wPos Integer -- Start Position of Window within Text String
Declare #roVal VarChar(8000)-- String Data to insert into output Table
Declare #BtchSiz Integer -- Maximum Size of Window
Set #BtchSiz = 7900 -- (Reset to smaller values to test routine)
Declare #dlPos Integer -- Position within Window of next Delimiter
Declare #Strt Integer -- Start Position of each data value within Window
-- -------------------------------------------------------------------------
-- ---------------------------
If #delim is Null Set #delim = '|'
If DataLength(#S) = 0 Or
Substring(#S, 1, #BtchSiz) = #delim Return
-- --------------------------------------------
Select #dlLen = DataLength(#delim),
#Strt = 1, #wPos = 1,
#wind = Substring(#S, 1, #BtchSiz)
Select #winLen = DataLength(#wind),
#isLastWin = Case When DataLength(#wind) = #BtchSiz
Then 0 Else 1 End,
#dlPos = CharIndex(#delim, #wind, #Strt)
-- --------------------------------------------
While #Strt <= #winLen
Begin
If #dlPos = 0 Begin -- No More delimiters in window
If #isLastWin = 1 Set #dlPos = #winLen + 1
Else Begin
Set #wPos = #wPos + #Strt - 1
Set #wind = Substring(#S, #wPos, #BtchSiz)
-- ----------------------------------------
Select #winLen = DataLength(#wind), #Strt = 1,
#isLastWin = Case When DataLength(#wind) = #BtchSiz
Then 0 Else 1 End,
#dlPos = CharIndex(#delim, #wind, 1)
If #dlPos = 0 Set #dlPos = #winLen + 1
End
End
-- -------------------------------
Insert #tOut (sVal)
Select LTrim(Substring(#wind,
#Strt, #dlPos - #Strt))
-- -------------------------------
-- Move #Strt to char after last delimiter
Set #Strt = #dlPos + #dlLen
Set #dlPos = CharIndex(#delim, #wind, #Strt)
End
Return
End
Then write, (using your table schema),
Declare #AllVals VarChar(8000)
Select #AllVals = Coalesce(#allVals + ',', '') + ID
From Table Where ID Is Not null
-- -----------------------------------------
Select sVal, Count(*)
From dbo.ParseTextString(#AllVals, ',')
Group By sval