MySQL Creating Stored Procedure to compare two values - mysql

I tried creating a stored procedure from the question below but when I test it using the values from my tables in my database, it is not giving me the correct output. Meaning if it should output 1, it outputs 2 instead.
Please help me figure what I did wrong.
Question and my sql statement is below.
Question: Create a stored procedure to compare the actual incomes of two employees. If the former is higher than the latter, output 1; otherwise, output 2.
Delimiter $$
CREATE PROCEDURE real_income(in employeeID_1 varchar(6), in employeeID_2 varchar(6),
out c int)
BEGIN
IF (SELECT income-outcome FROM salary WHERE employeeID=employeeID_1)>
(SELECT income-outcome FROM salary WHERE employeeID=employeeID_2) THEN SET c = 1;
ELSE SET c = 2;
END IF;
END $$
Sample data from salary table

You selection for the column is bad as mysql interprets it a subtraction of two columns.
So use backticks, or rename it
CREATE TABLE salary(employeeID INT,`income-outcome` DECIMAL(10,2))
INSERT INTO salary VALUEs (1,10.2),(2,20.2)
CREATE PROCEDURE real_income(in employeeID_1 varchar(6), in employeeID_2 varchar(6),
out c int)
BEGIN
IF (SELECT `income-outcome` FROM salary WHERE employeeID=employeeID_1)>
(SELECT `income-outcome` FROM salary WHERE employeeID=employeeID_2) THEN SET c = 1;
ELSE SET c = 2;
END IF;
END
CALL real_income(1,2,#i)
SELECT #i
| #i |
| -: |
| 2 |
db<>fiddle here
A better solution is this, so you can also check for equality
CREATE PROCEDURE real_income(in employeeID_1 varchar(6), in employeeID_2 varchar(6),
out c int)
BEGIN
SET c = (CASE WHEN (SELECT `income-outcome` FROM salary WHERE employeeID=employeeID_1)>
(SELECT `income-outcome` FROM salary WHERE employeeID=employeeID_2) THEN 1
WHEN (SELECT `income-outcome` FROM salary WHERE employeeID=employeeID_1) =
(SELECT `income-outcome` FROM salary WHERE employeeID=employeeID_2) THEN 0
ELSE 2 END);
END

Related

Error Code: 1172. Results consisted in more than one row error

So I have 2 tables named Employee(employeeID, salary) and Tax(employeeID, tax, revisedSalary), my aim is to calculate the tax and revised salary for all of the employees by extracting the values of the Salary column in the Employee Table, perform the calculations and store the results in the Tax table all this using stored procedures
Here is what I've tried to accomplish that, but without success so far, I'm getting 'Results consisted in more than one row' error:
delimiter //
create procedure calcTax()
begin
declare tax, salary, revisedSalary double default 0.0;
declare i int;
select Salary from Employee into salary;
while i <= salary do
if salary >= 0.0 and salary<= 10000.0
then
set tax = salary * 10/100;
set revisedSalary = salary - tax;
end if;
insert into Tax (tax, revisedSalary) values(tax, revisedSalary);
set i = i + 1;
end while;
end //
delimiter ;
Aside from the fact that you cannot store a result set in a variable your question doesn't make a lot of sense since you are attempting to calculate tax and salary per employee and you are inserting rows to tax without reference to employee. Also a while loop is unnecessary, the same can be achieved with a simple insert select
DROP TABLE IF EXISTS T,tax;
CREATE TABLE T
(employeeid int, salary int);
create table tax
(employeeid int, tax int , revisedsalary int);
insert into t values
(1,0),(2,5000),(3,7000),(4,15000);
insert into tax
select employeeid,
salary * .10,
salary - (salary * .10)
from t
where salary > 0 and salary <= 10000;
select * from tax;
+------------+------+---------------+
| employeeid | tax | revisedsalary |
+------------+------+---------------+
| 2 | 500 | 5000 |
| 3 | 700 | 7000 |
+------------+------+---------------+
2 rows in set (0.001 sec)
If you must us an sp
delimiter $$
create procedure p()
begin
insert into tax
select employeeid,
salary * .10,
salary - (salary * .10)
from t
where salary > 0 and salary <= 10000;
select * from tax;
end $$
delimiter ;
call p();

MySQL - copy or update rows with a change within one table

I have a database table like this one:
group | detailsID | price
EK | 1 | 1.40
EK | 2 | 1.50
EK | 3 | 1.60
H | 1 | 2.40
H | 2 | 2.50
Now I want to copy the data from group "EK" to the group "H", so the prices for the detailsID's must be adjusted for the detailsIDs 1 and 2, and the entry for detailsID 3 must be inserted for group "H".
How can I do that with one or two MySQL query's?
Thanks!
We can try doing an INSERT INTO ... SELECT with ON DUPLICATE KEY UPDATE:
INSERT INTO yourTable (`group`, detailsID, price)
SELECT 'H', detailsID, price
FROM yourTable t
WHERE `group` = 'EK'
ON DUPLICATE KEY UPDATE price = t.price;
But this assumes that there exists a unique key on (group, detailsID). If this would not be possible, then this approach would not work.
As an alternative, I might do this in two steps. First, remove the H group records, then insert the updated H records you expect.
DELETE
FROM yourTable
WHERE `group` = 'H';
INSERT INTO yourTable (`group`, detailsID, price)
SELECT 'H', detailsID, price
FROM yourTable
WHERE `group` = 'EK';
I use the above approach because a single update can't handle your requirement, since new records also need to be inserted.
Note that you should avoid naming your columns and tables using reserved MySQL keywords such as GROUP.
You can try this as well, Following code implemented using stored procedures. Very simple not that difficult to understand. You may need to modify data type and optimize the code as per the requirement.
DELIMITER $$;
DROP PROCEDURE IF EXISTS update_H $$;
CREATE PROCEDURE update_H()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE `group_col` varchar(255) DEFAULT "";
DECLARE `detaildid_col` varchar(255) DEFAULT "";
DECLARE `price_col` varchar(255) DEFAULT "";
DECLARE H_FOUND INTEGER DEFAULT 0;
DECLARE pull_data CURSOR FOR select `group`, `detaildid`, `price` from test.newtab WHERE `group` = 'EK';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN pull_data;
traverse_data: LOOP
FETCH pull_data INTO group_col, detaildid_col, price_col;
IF finished = 1 THEN
LEAVE traverse_data;
END IF;
SET H_FOUND = (SELECT count(*) from test.newtab where `group` = 'H' AND `detaildid` = detaildid_col);
IF ( H_FOUND = 1 ) THEN
UPDATE test.newtab SET `price` = price_col where `group` = 'H' AND `detaildid` = detaildid_col;
ELSE
INSERT INTO test.newtab (`group`, `detaildid`, `price`) VALUES ('H', detaildid_col, price_col);
END IF;
END LOOP traverse_data;
CLOSE pull_data;
END $$;
DELIMITER ;
You can call this procedure by executing, call update_H();

Debugging stored procedure in SQL group function

[
For the cname='Liam', there are 3 card_id
i.e. 87260101, 87260153, 87501026
We want to find out how many extra card_id this person has, means we want output=2.
For the cname='Elizabeth', there are 2 card_id.
i.e.87501022, 87501000 and we want an output of 1.
For the others who only has one card_id which correspond to an empty loss_report_date,
count(loss_report_date)=0, the output=0
For the code below, we get the error code=1111, invalid use of group function, but the store procedure does not report any error when we run procedure alone.
The DBMS we are using is Innodb.
DELIMITER $$
CREATE PROCEDURE Gettransaction(IN cname varchar(50), OUT cnt int)
BEGIN
#select card_id if there is no old_id, if t1.card_id=t2.old_id then use card_id
DECLARE maxcardid char(8);
DECLARE cnt int default 1;
DECLARE nextMax int;
set maxcardid = (select max(card_id) from card
group by cname);
WHILE cname in (select cname from card where count(loss_report_date)>=1)
DO
set nextMax = (select max(card_id)
from card
where card_id < maxcardid);
set cnt = cnt + 1;
set maxcardid = nextMax;
END WHILE;
END$$
DELIMITER ;
call Gettransaction('Liam', #output);
select #output

How do I use a recursive procedure in a loop in MySQL

I have an employees table with demographics data. This table has two fields I need: Employee ID and Manager ID. I need to build a join table that would look like this:
Employee IDManager ID
1 2
1 3
1 4
2 3
2 4
So I need the join table to show, for each employee, all the people above them. In case of employee 1 his direct manager is 2, his manager's manager is 3 and his manager's manager's manager is 4.
I have a MySQL procedure that seems to be working when called for an employee:
CREATE PROCEDURE chainReaction (IN employee_id int, IN orig_id int)
BEGIN
DECLARE manager_id int default NULL;
SET ##SESSION.max_sp_recursion_depth = 255;
SELECT ManagerID
INTO manager_id
FROM employees
WHERE EmployeeID = employee_id;
IF( manager_id is not null) THEN
INSERT INTO joinTable(EmpID, SupID) VALUES(
orig_id,manager_id
);
CALL chainReaction(manager_id, orig_id);
end if;
END;
Problem 1:
When calling chainReaction it looks like I need to provide the employee ID twice to the procedure because otherwise the original employee ID is 'lost' and the resulting inserts for employee 1 look like this:
Employee IDManager ID
1 2
2 3
4 4
So the Employee ID doesn't stay fixed to 1 as I needed it. Again, this procedure works when called as it is now: chainReaction(1,1);
But here's problem 2:
I have some code to loop through all rows in the employee table and call chainReaction on them:
CREATE PROCEDURE RowPerRow ()
BEGIN
DECLARE n int default 0;
DECLARE i int default 0;
DECLARE employee_id int default null;
SELECT COUNT(*) FROM employees INTO n;
SET i=0;
WHILE i<n DO
SELECT EmployeeID FROM employees WHERE LIMIT i,1 INTO employee_id;
CALL chainReaction(employee_id,employee_id);
END WHILE;
END;
The problem is that if I call this RowPerRow() procedure the employee column in the join table is stuck to the first employee ID no matter what row is being processed.
Looks like my procedures work just fine, what I was missing in the RowPerRow procedure is incrementing the counter (SET i = i + 1;). Here's the code fixed.
CREATE PROCEDURE RowPerRow ()
BEGIN
DECLARE n int default 0;
DECLARE i int default 0;
DECLARE employee_id int default null;
SELECT COUNT(*) FROM employees INTO n;
SET i=0;
WHILE i<n DO
SELECT EmployeeID FROM employees WHERE LIMIT i,1 INTO employee_id;
CALL chainReaction(employee_id,employee_id);
SET i = i + 1;
END WHILE;
END;

Stored procedure using if statement

I have here stored procedure:
delimiter //
create procedure insert(p int, n varchar(10), d date, q int)
begin
select pname if(pname!=n)
then
insert into prod(p,n,d,q)values(p,n,d,q)
else quant=quant + q;
from prod;
end;
//
This stored procedure will add records to the table prod if pname and n are not equal ELSE if they are equal, the quant will be updated and added by the value of q. This idea is not working can you help me? How to achieve this one?
....
BEGIN
DECLARE p CHAR DEFAULT NULL;
SELECT pname FROM prod WHERE pname = n LIMIT 1 INTO p FOR UPDATE;
IF(p) THEN
UPDATE prod SET quant = quant + q WHERE pname = n;
ELSE
INSERT INTO prod(p,n,d,q) values(p,n,d,q);
END IF;
END;
There are simpler ways to do it if you have a UNIQUE key on pname in prod.