Reputation: 2914
Selecting distinct values from the above result set i.e, thereby eliminating duplicate values and finally storing these values into a variable with a comma-separated list of values. Such that variable assigned with a comma-separated list of values must be given as an input to another SQL IN Operator
DELIMITER $$
USE `someDB`$$
DROP PROCEDURE IF EXISTS `AAA`$$
CREATE PROCEDURE `AAA`(IN `feed_setting_user_id` BIGINT)
READS SQL DATA
DETERMINISTIC
SQL SECURITY INVOKER
BEGIN
DECLARE FoFID, FoFUsername, friendID, friendUsername TEXT;
DECLARE exit_loop BOOLEAN DEFAULT FALSE;
DECLARE friend_cursor CURSOR FOR
SELECT `u`.`ID`, `u`.`username` FROM `users` `u`
WHERE `u`.`ID` IN (SELECT `u1`.`ID` FROM users `u1`
WHERE `u1`.`ID` IN
(SELECT `uf`.`friendid` FROM user_friends `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = feed_setting_user_id )
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = feed_setting_user_id)
AND `u1`.`ID` != feed_setting_user_id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN friend_cursor;
friend_loop: LOOP
FETCH FROM friend_cursor INTO friendID, friendUsername;
IF exit_loop THEN
LEAVE friend_loop;
END IF;
-- SELECT friendID, friendUsername;
SELECT `u`.`ID`, `u`.`username` FROM `users` `u` WHERE `u`.`ID` NOT IN (feed_setting_user_id) AND `u`.`ID`
IN (SELECT `u1`.`ID` FROM `users` `u1`
WHERE `u1`.`ID` IN (SELECT `uf`.`friendid` FROM `user_friends` `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = friendID AND `uf`.`friendid` != friendID)
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = friendID AND `uf2`.`userid` != friendID) AND `u1`.`ID` != friendID );
END LOOP friend_loop;
CLOSE friend_cursor;
END $$
DELIMITER ;
Actual Result:
+----+-----------+
| ID | username |
+----+-----------+
| 5 | SpiderMan |
| 8 | AntMan |
| 9 | Bat |
| 11 | SuperMan |
| 12 | Arrow |
| 13 | CAmerica |
+----+-----------+
6 rows in set (0.53 sec)
+----+----------+
| ID | username |
+----+----------+
| 9 | Bat |
| 10 | BatMan |
| 13 | mustafa |
+----+----------+
3 rows in set (0.61 sec)
+----+-----------+
| ID | username |
+----+-----------+
| 5 | SpiderMan |
| 6 | Hulk |
| 9 | Bat |
| 10 | BatMan |
+----+-----------+
4 rows in set (0.69 sec)
+----+----------+
| ID | username |
+----+----------+
| 8 | AntMan |
| 9 | Bat |
| 10 | BatMan |
| 11 | SuperMan |
+----+----------+
4 rows in set (0.78 sec)
Query OK, 0 rows affected (0.86 sec)
Expected Result:
5,6,8,9,11,12,10,13
We need to assign the above list of comma separated values into a variable. So that we need to eliminate duplicates from the above list of values.
Update:
Tried to implement nested cursors
DELIMITER $$
USE `someDB`$$
DROP PROCEDURE IF EXISTS `AAA`$$
CREATE PROCEDURE `AAA`(IN `feed_setting_user_id` BIGINT)
READS SQL DATA
DETERMINISTIC
SQL SECURITY INVOKER
BEGIN
DECLARE FoFID, FoFUsername, friendID, friendUsername TEXT;
DECLARE exit_loop BOOLEAN DEFAULT FALSE;
DECLARE exit_loop1 BOOLEAN DEFAULT FALSE;
DECLARE friend_cursor CURSOR FOR
SELECT `u`.`ID`, `u`.`username` FROM `users` `u`
WHERE `u`.`ID` IN (SELECT `u1`.`ID` FROM users `u1`
WHERE `u1`.`ID` IN
(SELECT `uf`.`friendid` FROM user_friends `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = feed_setting_user_id )
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = feed_setting_user_id)
AND `u1`.`ID` != feed_setting_user_id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
OPEN friend_cursor;
friend_loop: LOOP
FETCH FROM friend_cursor INTO friendID, friendUsername;
IF exit_loop THEN
LEAVE friend_loop;
END IF;
-- SELECT friendID, friendUsername;
DECLARE friend_of_friend_cursor CURSOR FOR
SELECT `u`.`ID`, `u`.`username` FROM `users` `u` WHERE `u`.`ID` NOT IN (feed_setting_user_id) AND `u`.`ID`
IN (SELECT `u1`.`ID` FROM `users` `u1`
WHERE `u1`.`ID` IN (SELECT `uf`.`friendid` FROM `user_friends` `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = friendID AND `uf`.`friendid` != friendID)
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = friendID AND `uf2`.`userid` != friendID) AND `u1`.`ID` != friendID );
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop1 = TRUE;
OPEN friend_of_friend_cursor;
friend_of_friend_loop: LOOP
FETCH FROM friend_of_friend_cursor INTO FoFID, FoFUsername;
IF exit_loop1 THEN
LEAVE friend_of_friend_loop;
END IF;
SELECT FoFID, FoFUsername;
END LOOP friend_of_friend_loop;
CLOSE friend_of_friend_cursor;
END LOOP friend_loop;
CLOSE friend_cursor;
END $$
DELIMITER ;
Results:
Error Code: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DECLARE friend_of_friend_cursor CURSOR FOR
SELECT `u`.`ID`, `u`.`user' at line 29
Upvotes: 1
Views: 744
Reputation: 1829
Try the below sp
DELIMITER $$
USE `someDB`$$
DROP PROCEDURE IF EXISTS `AAA`$$
CREATE PROCEDURE `AAA`(IN `feed_setting_user_id` BIGINT)
modifies SQL DATA
DETERMINISTIC
SQL SECURITY INVOKER
BEGIN
DECLARE v_friendID, FoFID bigint; # use datatype which is used for u.ID used int based on ur result
DECLARE exit_loop, exit_loop1 BOOLEAN DEFAULT FALSE;
DECLARE friend_cursor CURSOR FOR
SELECT `u`.`ID` FROM `users` `u`
WHERE `u`.`ID` IN (SELECT `u1`.`ID` FROM users `u1`
WHERE `u1`.`ID` IN
(SELECT `uf`.`friendid` FROM user_friends `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = feed_setting_user_id )
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = feed_setting_user_id)
AND `u1`.`ID` != feed_setting_user_id);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;
drop temporary table if exists unique_tbl; #precaution: when sp stops with error
create temporary table unique_tbl (user_id bigint unique); #to avoid duplicate added unique
insert into unique_tbl values (feed_setting_user_id); # added input from sp
OPEN friend_cursor;
friend_loop: LOOP
FETCH friend_cursor INTO v_friendID;
IF exit_loop THEN
LEAVE friend_loop;
ELSE
replace into unique_tbl values (v_friendID); # since we need all unique id's using replace if exists
fof: begin
DECLARE friend_of_friend_cursor CURSOR FOR
SELECT `u`.`ID` FROM `users` `u` WHERE `u`.`ID` NOT IN (feed_setting_user_id) AND `u`.`ID`
IN (SELECT `u1`.`ID` FROM `users` `u1`
WHERE `u1`.`ID` IN (SELECT `uf`.`friendid` FROM `user_friends` `uf` WHERE `uf`.`status` = '2' AND `uf`.`userid` = v_friendID AND `uf`.`friendid` != v_friendID)
OR `u1`.`ID` IN (SELECT `uf2`.`userid` FROM `user_friends` `uf2` WHERE `uf2`.`status` = '2' AND `uf2`.`friendid` = v_friendID AND `uf2`.`userid` != v_friendID)
AND `u1`.`ID` != v_friendID );
DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop1 = TRUE;
OPEN friend_of_friend_cursor;
friend_of_friend_loop: LOOP
FETCH friend_of_friend_cursor INTO FoFID;
IF exit_loop1 THEN
LEAVE friend_of_friend_loop;
END IF;
replace into unique_tbl values (FoFID);
END LOOP friend_of_friend_loop;
CLOSE friend_of_friend_cursor;
end;
end if;
END LOOP friend_loop;
CLOSE friend_cursor;
select group_concat(user_id) from unique_tbl; #this will show result in comma seperated 2,34,56,78
#cleanup
drop temporary table if exists unique_tbl;
END $$
DELIMITER ;
Upvotes: 1