Error 1248: Every derived table must have its own alias - mysql

Please see my code, below. I get the error:
Error 1248: Every derived table must have its own alias
What am I doing wrong?
CREATE PROCEDURE `insert_seance` (IN compared_id INT)
BLOCK1: BEGIN
CREATE TEMPORARY TABLE log
LIKE seance_log;
CREATE TEMPORARY TABLE compared_log
LIKE seance_log;
BLOCK2: BEGIN
DECLARE done, inner_done BOOLEAN DEFAULT FALSE;
DECLARE diff BOOL DEFAULT TRUE;
DECLARE current_id, se_id, q_id, ans INT;
DECLARE compared CURSOR FOR
SELECT seance_id, question_id, answer FROM seance_log
WHERE seance_id = compared_id;
DECLARE seance CURSOR FOR
SELECT seance_id FROM seances
WHERE seance_id <> compared_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN compared;
WHILE NOT done DO
FETCH compared INTO se_id, q_id, ans;
INSERT INTO compared_log (seance_id, question_id, answer)
VALUES (se_id, q_id, ans);
END WHILE;
CLOSE compared;
SET done = FALSE;
OPEN seance;
WHILE NOT done DO
FETCH seance INTO current_id;
DELETE FROM log;
BLOCK3: BEGIN
DECLARE answers CURSOR FOR
SELECT seance_id, question_id, answer FROM seance_log
WHERE seance_id = current_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET inner_done = TRUE;
DELETE FROM log;
OPEN answers;
WHILE NOT inner_done DO
FETCH answers INTO se_id, q_id, ans;
INSERT INTO log (seance_id, question_id, answer)
VALUES (se_id, q_id, ans);
END WHILE;
CLOSE answers;
SELECT IF ((SELECT COUNT(*) FROM (SELECT 'log' AS `set`, l.*
FROM log l
WHERE ROW(l.seance_id, l.question_id, l.answer) NOT IN
(SELECT * FROM compared_log)
UNION ALL
SELECT 'compared_log' AS `set`, cl.*
FROM compared_log cl
WHERE ROW(cl.seance_id, cl.question_id, cl.answer) NOT IN
(SELECT * FROM log)
)),FALSE,TRUE) INTO diff;
CASE WHEN diff = FALSE
THEN DELETE FROM seance_log
WHERE seance_id = compared_id;
UPDATE seances SET count = count + 1
WHERE seance_id = compared_id;
END CASE;
SET done = NOT diff;
END BLOCK3;
END WHILE;
CLOSE seance;
END BLOCK2;
END BLOCK1

Related

Nested Cursors in MYSQL, cursor not working as expected

I have created an SP in MYSQL to get values by date, by the sensor. My SP executes the inner cursor correctly but the outer cursor(1st cursor) is not executed. i.e. I only get 1 day of data, dateTable has a week's data.
CREATE PROCEDURE `Analysis`()
BEGIN
declare v_date datetime;
declare v_sensor varchar(50);
DECLARE datecursHandler,sensorCursHandler BOOLEAN DEFAULT FALSE;
Block1: BEGIN
declare datecursor CURSOR for
select distinct date from dateTable;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET datecursHandler = TRUE;
Open datecursor;
datecurs: loop
FETCH datecursor into date;
IF datecursHandler THEN
CLOSE datecursor;
LEAVE datecurs;
END IF;
Block2: BEGIN
declare sensorCursor CURSOR for
select distinct sensor from sensorTable ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET sensorcur = TRUE;
Open sensorCursor;
senscurs: loop
FETCH sensorCursor into sensor;
IF sensorcur THEN
SET sensorcur = False;
CLOSE sensorCursor;
LEAVE senscurs;
END IF;
Insert into temptable(
sensorValue,
DateID,
TimeID,
TotalCount,
TotalDistinctCount
)
SELECT
sensor AS sensorValue,
DATE_FORMAT(firstdate, '%Y%m%d') AS DateID,
HOUR(firstdate) + 1 AS TimeID,
COUNT(*) AS totalcount,
COUNT(DISTINCT sensor) AS sensordistinctcount
FROM
(SELECT
sensor AS sensor,
first_seen AS DeviceFirstSeen,
last_seen AS DeviceLastSeen,
DATE_FORMAT(FROM_UNIXTIME(first_seen), '%Y/%m/%d %k:%i:%s.%f') AS firstdate,
DATE_FORMAT(FROM_UNIXTIME(last_seen), '%Y/%m/%d %k:%i:%s.%f') AS lastdate,
FROM
sensorTable
INNER JOIN sensorTable2 ON sensorTable.ID = sensorTable2.ID
WHERE sensorTable.DeviceFirstSeen BETWEEN date_format(date_sub(date,interval 1 day),'%Y-%m-%d 15:00:00') AND date_format(date,'%Y-%m-%d 14:59:59')) a
GROUP BY DATE_FORMAT(firstdate, '%Y%m%d') , HOUR(firstdate) + 1;
end loop Maccurs;
END Block2;
END loop datecurs;
END Block1;
END
Can anyone please help me debug my code? I have researched but so far my code looks correct as per my research but doesn't work as expected.
Required Output:
Get counts of all the sensors for each day each hour that is selected from dateTable.
Try the below procedure, Since the issue might be incorrect closing of cursor.
CREATE PROCEDURE `Analysis`()
BEGIN
declare v_date datetime;
declare v_sensor varchar(50);
DECLARE datecursHandler,sensorCursHandler BOOLEAN DEFAULT FALSE;
Block1: BEGIN
declare datecursor CURSOR for
select distinct date from dateTable;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET datecursHandler = TRUE;
select distinct date from dateTable; #what is the result set you are getting?
Open datecursor;
datecurs: loop
FETCH datecursor into v_date;
IF datecursHandler THEN
LEAVE datecurs;
END IF;
Block2: BEGIN
declare sensorCursor CURSOR for
select distinct sensor from sensorTable ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET sensorCursHandler = TRUE;
Open sensorCursor;
senscurs: loop
FETCH sensorCursor into v_sensor;
IF sensorCursHandler THEN
SET sensorCursHandler = false;
LEAVE senscurs;
END IF;
Insert into temptable(
sensorValue,
DateID,
TimeID,
TotalCount,
TotalDistinctCount
)
SELECT
sensor AS sensorValue,
DATE_FORMAT(firstdate, '%Y%m%d') AS DateID,
HOUR(firstdate) + 1 AS TimeID,
COUNT(*) AS totalcount,
COUNT(DISTINCT sensor) AS sensordistinctcount
FROM
(SELECT
sensor AS sensor,
first_seen AS DeviceFirstSeen,
last_seen AS DeviceLastSeen,
DATE_FORMAT(FROM_UNIXTIME(first_seen), '%Y/%m/%d %k:%i:%s.%f') AS firstdate,
DATE_FORMAT(FROM_UNIXTIME(last_seen), '%Y/%m/%d %k:%i:%s.%f') AS lastdate,
FROM
sensorTable
INNER JOIN sensorTable2 ON sensorTable.ID = sensorTable2.ID
WHERE sensorTable.DeviceFirstSeen BETWEEN date_format(date_sub(date,interval 1 day),'%Y-%m-%d 15:00:00') AND date_format(date,'%Y-%m-%d 14:59:59')) a
GROUP BY DATE_FORMAT(firstdate, '%Y%m%d') , HOUR(firstdate) + 1;
end loop senscurs;
close sensorCursor;
END Block2;
END loop datecurs;
close datecursor;
END Block1;
END

Want to return data set from this cursor ,stored procedure

i am working on this stored procedure , can any body please help me to get data set from this procedure .
*Create a stored procedure with a variable entry called list_g
This is the procedure (see attached):
and then:
*=at
SET *list = "";
CALL getNodes(*list);
select *list;
Here is the Stored Procedure :
BEGIN
DECLARE done1, done2 BOOLEAN DEFAULT FALSE;
DECLARE row1 varchar(900) default "";
DECLARE parentId INTEGER;
DECLARE cur1 CURSOR FOR SELECT idIncidence FROM incidence
WHERE DATE(dateTimeIn_dt)='2018-01-18' and hour(TIME(dateTimeIn_dt))
BETWEEN '08' and '15';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1 = TRUE;
open cur1;
loop1: LOOP
FETCH cur1 INTO parentId;
IF done1 THEN
CLOSE cur1;
LEAVE loop1;
END IF;
set list_g=CONCAT(parentId,";",list_g);
BLOCK1 : BEGIN
DECLARE cur2 CURSOR FOR SELECT
a.idIncidence,DATE_FORMAT(dateTimeIn_dt,'%H:%i:%s') as dateTimeIn_dt,0
as conteo, a.classification_str,measure_n,a.keyNode_str_fk,(
SELECT GROUP_CONCAT( nameStation_str SEPARATOR ', ') AS
idStation
FROM (
SELECT nameStation_str,
( 6371 * acos(cos(radians((SELECT lat from incidence where
idIncidence =#parentId))) * cos(radians(lat_str)) *
cos(radians(lon_str) - radians((SELECT lon from incidence where
idIncidence =#parentId))) + sin(radians((SELECT lat from incidence
where idIncidence =#parentId))) * sin(radians(lat_str))) )
AS distance
FROM station HAVING distance < 0.01 ORDER BY distance
) as s
)as
idStation_fk,kp.kindProtective_str,m.nameModel_str
,pa.keyArea_n,kp.idKinProtector FROM incidence a
JOIN node n on a.keyNode_str_fk=n.keyNode_str
JOIN protective pr on n.idProtective_fk=pr.idProtective
JOIN kindProtector kp on pr.idKindProtector_fk=kp.idKinProtector
JOIN model m on pr.idModel_fk=m.idModel
JOIN station st on a.idStation_fk =st.idStation
JOIN branch br on st.idBranch_fk=br.idBranch
JOIN ship sh on br.idShip_fk=sh.idShip
JOIN protectiveArea pa on n.idProtectiveArea=pa.idProtectiveArea
WHERE DATE(dateTimeIn_dt)='2018-01-18' and
hour(TIME(dateTimeIn_dt)) BETWEEN '08' and '15';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2 = TRUE;
OPEN cur2;
loop2 : LOOP
if done2 THEN
CLOSE cur2;
SET done2 = FALSE;
LEAVE loop2;
END IF;
END LOOP loop2;
END BLOCK1;
END loop loop1;
END
i need to return all the data set from the query
Please help me in this problem. Here are my Tables Name :
Branch , brand ,group_node ,incidence ,kindProtector,model,node,plant,protective,protectiveArea,protectiveGroup,sensor,shift,ship,station,user .

1172 - Result consisted of more than one row in mysql

How can I solve this problem (Result consisted of more than one row in mysql)
DROP PROCEDURE IF EXISTS `doMarksApplication`;
CREATE PROCEDURE `doMarksApplication`(
in kuser varchar(20),
out idpro int(11))
SP:BEGIN
declare no_more_rows int default FALSE;
declare total_marks decimal(10,2) default 0;
declare idfor int(11) default 0;
declare sskod int(5) default getCurSession();
declare bdata int(5) default 0;
declare nopmh varchar(20);
# Data PB [Permohonan Baru] DM [Proses Pemarkahan]
declare cur1 cursor for
select ind_nopmh from pinduk
left join pprses on pro_nopmh = ind_nopmh
where ind_sskod = sskod and
concat(pro_stats,pro_statp) in ('PB','DM') and
not exists (select mar_idnum from pmrkah where mar_nopmh = ind_nopmh)
order by ind_nopmh;
declare continue handler for not found set no_more_rows = TRUE;
begin
select count(ind_nopmh) into bdata
from pinduk
left join pprses on pro_nopmh = ind_nopmh
where ind_sskod = sskod and
concat(pro_stats,pro_statp) in ('PB','DM') and
not exists (select mar_idnum from pmrkah where mar_nopmh = ind_nopmh);
end;
begin
select count(for_idnum) into idfor from xkod_markah_00_formula
where for_stats = 'A' and
curdate() between for_tkhdr and for_tkhhg;
end;
if idfor = 1 and sskod <> 0 then
begin
select for_idnum into idfor from xkod_markah_00_formula
where for_stats = 'A' and
curdate() between for_tkhdr and for_tkhhg;
end;
begin
insert into pprmar
(pma_tkmla,pma_msmla,pma_puser,pma_sskod,pma_idfor,pma_bdata)
values
(curdate(),curtime(),kuser,sskod,idfor,bdata);
end;
begin
select last_insert_id() into idpro;
end;
open cur1;
LOOP1:loop
fetch cur1 into nopmh;
if no_more_rows then
close cur1;
leave LOOP1;
end if;
begin
call getMarksAnakPerak(nopmh,#total_perak);
call getMarksAkademik(nopmh,#total_akdmk);
call getMarksSosioekonomi(nopmh,#total_sosio);
end;
set total_marks = #total_perak + #total_akdmk + #total_sosio;
begin
insert into pmrkah
(mar_idpro,mar_nopmh,mar_idfor,mar_perak,mar_akdmk,mar_sosio,mar_total)
values
(idpro,nopmh,idfor,#total_perak,#total_akdmk,#total_sosio,total_marks);
end;
begin
update pprses
set pro_stats = 'D',
pro_statp = 'M',
pro_tkmsk = curdate(),
pro_msmsk = curtime(),
pro_kuser = kuser
where pro_nopmh = nopmh;
end;
end loop;
begin
update pprmar
set pma_tktmt = curdate(),
pma_mstmt = curtime()
where pma_idnum = idpro;
end;
end if;
END;
i have been programming in mysql for 15 years and this is easily the most confusing stored procedure i have ever seen.
None the less, one possible place for your issue is here
select for_idnum into idfor from xkod_markah_00_formula
where for_stats = 'A' and
curdate() between for_tkhdr and for_tkhhg;
I know it does not seem to be the reason but without knowing the content of the other three stored procedures you are calling this is the only candidate. You should add a limit 1 to it, and to every select into statement that reads from a table (i.e. not a sum() or a count() etc...) as that would always have the potential to cause the error you are seeing.
select for_idnum into idfor from xkod_markah_00_formula
where for_stats = 'A' and
curdate() between for_tkhdr and for_tkhhg limit 1;
In addition, you should comment out the three stored procedure calls and see if the error goes away. My guess is that the issue is one of those stored procedures due to a select into similar to above has more than one row in the result set but does not use limit 1 and does not filter properly.

Mysql Function - not sure where to start

I would like to write a function in Mysql that from a given product code return a formatted string
Here is an example of the calls I need to manually make now to get the result I want.
SELECT p.productcategoryid from products p where (isnull(p.endeffdt) or (p.endeffdt = '0000-00-00') or (p.endeffdt > now())) and p.code='T29R66N1';
T29R66NQ is the product code I need the full path for - the above call returns '38' as the category ID.
I then perform the following select based on the result from above
SELECT name,parentid,productcategorypath FROM productcategory WHERE recid = '38';
This returns
name->Built-In Hobs
parentid->7
productcategorypath=222,7,38
Using that result I then
SELECT name,parentid,productcategorypath FROM productcategory WHERE recid = '7';
giving me
name->Built-In
parentid->222
productcategorypath=222,7
and again, I then do
SELECT name,parentid,productcategorypath FROM productcategory WHERE recid = '222';
which in turn gives me
name->Kitchen & Home Appliances
parentid->0
productcategorypath=222
I stop there because parentid = 0 (it may go on for more iterations but will always end with parent id of 0) but i need the results from the last 3 selects to give me the following string
Kitchen & Home Appliances > Built-In > Built-In Hobs
I would like a mysql function whereby I can use it like
select getpath(code) from products where code='T29R66N1'
Any help would be appreciated.
EDIT:
I managed to figure it myself - here is my function
DROP FUNCTION IF EXISTS mydb.getpath;
CREATE FUNCTION mydb.getpath (itemid VARCHAR(20))
RETURNS varchar(255)
BEGIN
DECLARE path_name varchar(255);
DECLARE tmp_name varchar(255);
DECLARE tmp_parentid INT;
DECLARE tmp_parentid1 INT;
SELECT p.productcategoryid INTO tmp_parentid from products p where (isnull(p.endeffdt) or (p.endeffdt = '0000-00-00') or (p.endeffdt > now())) and p.code=itemid;
myloop:LOOP
SELECT name,parentid INTO tmp_name,tmp_parentid1 FROM productcategory WHERE recid = tmp_parentid;
SET path_name = concat_ws(' > ', tmp_name,path_name);
IF tmp_parentid1!=0 THEN
SET tmp_parentid = tmp_parentid1;
ITERATE myloop;
ELSE
LEAVE myloop;
END IF;
END LOOP;
RETURN path_name;
END;
DROP FUNCTION IF EXISTS mydb.getpath;
CREATE FUNCTION mydb.getpath (itemid VARCHAR(20))
RETURNS varchar(255)
BEGIN
DECLARE path_name varchar(255);
DECLARE tmp_name varchar(255);
DECLARE tmp_parentid INT;
DECLARE tmp_parentid1 INT;
SELECT p.productcategoryid INTO tmp_parentid from products p where (isnull(p.endeffdt) or (p.endeffdt = '0000-00-00') or (p.endeffdt > now())) and p.code=itemid;
myloop:LOOP
SELECT name,parentid INTO tmp_name,tmp_parentid1 FROM productcategory WHERE recid = tmp_parentid;
SET path_name = concat_ws(' > ', tmp_name,path_name);
IF tmp_parentid1!=0 THEN
SET tmp_parentid = tmp_parentid1;
ITERATE myloop;
ELSE
LEAVE myloop;
END IF;
END LOOP;
RETURN path_name;
END;

No data return after calling the stored procedures with multiple cursors in it

I have a stored procedures with the following code. The reason i use cursor is to join table which something will return NULL value and cause the record to be disappear. By using this method, I am able to get all data without losing any.
The only problem now is that when i try to call the stored precedures, it return
Error Code : 1329
No data - zero rows fetched, selected, or processed
but when i do a manual select * from TMOMain, the table is created and there is data in it but no data from SignUpCur and UnSubCur mean it was not updated.
1st time using mysql stored procedures so there might be something i miss out.
My Code
ROOT:BEGIN
DECLARE pTotal,pShortCode,pSignUp,pUnSub,pJunk,pT INT;
DECLARE pTc NVARCHAR(10);
DECLARE SignTotal,UnSubTotal, JunkTotal INT;
DECLARE pSignTotal,pSignTeamID,pUnSubTotal,pUnSubT,pSignUpS,pUnSubS INT;
DECLARE pSignTeam,pUnSubTeam NVARCHAR(10);
DECLARE no_more_rows BOOLEAN;
DECLARE MoMainCur CURSOR FOR
SELECT COUNT(*) AS GrandTotal,pShort,(CASE WHEN r= 1 THEN 'A'
WHEN r= 2 THEN 'B' WHEN r= 3 THEN 'C' ELSE 'UV' END) AS Team,recvTeamID
FROM tbli
INNER JOIN tblK ON keywordid = rkey
WHERE recvDate >='2011-11-15' AND recvDate < '2011-11-16'
GROUP BY pShort,Team,recvTeamID;
DECLARE SignUpCur CURSOR FOR
SELECT COUNT(*) AS SignUp,(CASE WHEN r= 1 THEN 'A'
WHEN r= 2 THEN 'B' WHEN r= 3 THEN 'C' ELSE 'UV' END) AS Team,
recvTeamID,pShort
FROM tbli INNER JOIN tbl_user ON recvphone = userphone
INNER JOIN tblK ON keywordid = userpublicstatus
WHERE userdatejoined >='2011-11-15' AND userdatejoined < '2011-11-16'
AND recvdate >='2011-11-15' AND recvdate < '2011-11-16'
GROUP BY Team,recvTeamID,pShort;
DECLARE UnSubCur CURSOR FOR
SELECT COUNT(*) AS UnSub,(CASE WHEN r= 1 THEN 'A'
WHEN r= 2 THEN 'B' WHEN r= 3 THEN 'C' ELSE 'UV' END) AS Team,
recvTeamID,pShort
FROM tbliINNER JOIN tbl_user ON recvphone = userphone
INNER JOIN tblK ON keywordid = userpublicstatus
WHERE userdateExpire >='2011-11-15' AND userdateExpire <'2011-11-16'
AND recvdate >='2011-11-15' AND recvdate < '2011-11-16'
GROUP BY Team,recvTeamID,pShort;
DROP TABLE IF EXISTS `TMoMain`;
CREATE TEMPORARY TABLE TMOMain
(GrandTotal INT,ShortCode INT,Team NVARCHAR(10),SignUp INT,UnSub INT, Junk INT, TeamID INT);
OPEN MoMainCur;
-- Main Table
read_loop:LOOP
FETCH MoMainCur INTO pTotal,pShortCode,pTc,pT;
INSERT INTO TMOMain
VALUES
(pTotal,pShortcode,pTc,0,0,0,pT);
END LOOP read_loop;
CLOSE MoMainCur;
-- Insert Signup Details into Main Table
OPEN SignUpCur;
SignUp_Loop:LOOP
FETCH SignUpCur INTO pSignTotal,pSignTeam,pSignTeamID,pSignUpS;
UPDATE TMOMain
SET SignUp = pSignTotal
WHERE Team = pSignTeam AND Shortcode =pSignUpS;
END LOOP SignUp_Loop;
CLOSE SignUpCur;
-- Insert UnSub Details into Main Table
OPEN UnSubCur;
UnSub_Loop:LOOP
FETCH UnSubCur INTO pUnSubTotal,pUnSubTeam,pUnSubT,pUnSubS;
UPDATE TMOMain
SET UnSub = pSignTotal
WHERE Team = pUnSubTeam AND pShort = pUnSubShortCode;
END LOOP UnSub_Loop;
CLOSE UnSubCur;
SELECT * FROM TMOMain;
END$$
Please try this out:
Add this declaration once (at the top):
DECLARE curIsDone INT DEFAULT FALSE;
Then after you declare your cursor add this:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET curIsDone = TRUE;
After your FETCH commands and before the actions you intend to perform:
IF curIsDone THEN
LEAVE read_loop;
END IF;