Building an table using procedures - mysql

i'm trying to create an procedure that returns an table with some information of my database, it lists the number of the HOTEL by how many clients used each type of their credit cards on the hotel
Keeping in mind that there is more than 50 hotels and 3 types of credit cards, i want the procedure to run through the data and list then in the table
DELIMITER //
DROP PROCEDURE IF EXISTS `testing` //
CREATE PROCEDURE `testing`(OUT param1 VARCHAR(40))
BEGIN
DECLARE id_cnpjEstabelecimento VARCHAR(40);
DECLARE id_redeCartão VARCHAR(255);
SELECT (cnpjEstabelecimento)
FROM fpcsmovatlantica201308tst04;
SET id_cnpjEstabelecimento := cnpjEstabelecimento;
SELECT (id_redeCartão)
FROM fpcsmovatlantica201308tst04;
SET id_redeCartão := id_redeCartão;
SELECT count(*)
FROM fpcsmovatlantica201308tst04;
WHERE redeCartão like 'id_redeCartão%';
AND cnpjEstabelecimento like 'id_cnpjEstabelecimento%';
END //
DELIMITER ;
An example of an select
SELECT count(*)
FROM fpcsmovatlantica201308tst04
WHERE redeCartão like 'Cielo%'
AND cnpjEstabelecimento like '02223966000466%'
the cnpjEstabelecimento got several values, more than 100+, so it's inviable to make all the selects
I don't even have to use procedures to make it, the final result was
SELECT cnpjEstabelecimento, redeCartão, count(*)
FROM fpcsmovatlantica201308tst04
WHERE redeCartão like 'Cielo%'
GROUP BY cnpjEstabelecimento,redeCartão like 'Cielo%'
ORDER BY cnpjEstabelecimento ASC;

I'm assuming you have one table, which looks kind of like this:
|hotelId|cardType|etc...
I'd go with:
Select hotelId, cardType, count(*)
from myTable
group by hotelId, cardType
I tested it here with the following SQL:
SELECT country, city, count(*)
from customers
group by country, city
ORDER BY Country;

Related

Create stored procedure with mutliple output categories in MySQL

I am working in MySQL Workbench and using the following SQL sample data. https://www.databasestar.com/sample-database-superheroes/
My diagram is attached at the bottom.
How do I create a stored procedure where you input the name of a superhero (e.g. Firebird) and get which specific fire-themed superpower they have?
So far, my code looks like this:
DROP PROCEDURE IF EXISTS Elemental_Heroes;
DELIMITER $$
CREATE PROCEDURE Elemental_Heroes(
IN HeroName VARCHAR(250),
OUT ElementalCat VARCHAR(250))
BEGIN
DECLARE credit DECIMAL DEFAULT 0;
SELECT
s.id,
s.superhero_name,
sp.power_name
FROM superhero s
LEFT JOIN hero_power hp ON s.id = hp.hero_id
LEFT JOIN superpower sp ON hp.power_id = sp.id
WHERE sp.id IN (56,79,90,104,140) AND s.superhero_name = HeroName
GROUP BY s.id, s.superhero_name, sp.power_name;
IF
ELSE
END$$
DELIMITER ;
CALL Elemental_Heroes(Firebird);
Where the IF ELSE part is just a placeholder for the conditional statements I know must eventually be there. The entire elect part (minus the s.superhero_name = HeroName) runs as desired.
I'm also wondering if there's any way for the output to be multiple categories. Because Firebird has Fire Control, Fire Resistance, and Heat Resistance and I would like all three categories to be the output when I call Elemental_Heroes(Firebird).
A sample.
Create source data
CREATE TABLE main
SELECT 1 id, 'Name 1' name UNION SELECT 2, 'Name 2' UNION SELECT 3, 'Name 3';
CREATE TABLE slave
SELECT 1 id, 1 val UNION SELECT 1, 2 UNION SELECT 2, 3 UNION
SELECT 2, 1 UNION SELECT 3, 2 UNION SELECT 3, 3;
Create stored procedure which retrieves names list by provided val value
CREATE PROCEDURE get_id_by_val (IN in_val INT, OUT out_names_list TEXT)
BEGIN
SELECT JSON_ARRAYAGG(name) INTO out_names_list
FROM main
JOIN slave USING (id)
WHERE slave.val = in_val;
END
SP queries the names by the value provided in in_val input parameter and saves found values into out_names_list output parameter
Using SP
CALL get_id_by_val(3, #output);
-- retrieve the list as solid JSON array
SELECT #output;
-- retrieve the same in separate rows
SELECT name FROM JSON_TABLE(#output, '$[*]' COLUMNS (name VARCHAR(255) PATH '$')) jsontable
In CALL we provide criteria value for in_val parameter and use user-defined variable #output as a place where the output will be placed into.
Solid JSON array output
#output
["Name 2", "Name 3"]
Output parsed to separate values
name
Name 2
Name 3
fiddle

Assign Query String in a variable

In mySQL stored procedure how can I assign a Query String to a variable, so I can reuse it? In my example I will be using SELECT id FROM audit many times.
CREATE PROCEDURE my_proc()
BEGIN
UPDATE person SET status='Active' WHERE id = (SELECT id FROM audit);
SELECT COUNT(*) FROM (SELECT id FROM audit);
//Multile scenarios the `SELECT id FROM audit` will be used.
END
Something like:
CREATE PROCEDURE my_proc()
BEGIN
myVariable = SELECT id FROM audit;
UPDATE person SET status='Active' WHERE id = (myVariable;
SELECT COUNT(*) FROM (myVariable);
//Multile scenarios the `SELECT id FROM audit` will be used.
END
Is this what you are looking for? Sorry I am not sure what you need.
SELECT #myCount:= count(id) FROM audit;
select #myCount;
Based on your reply, do you need a temporary table to store the ids from the audit and re-use those on the queries?
create temporary table tbl_tmp_audit;
select id from audit;
I am assuming you need this so that you won't join the whole audit columns every time on your succeeding queries.
--first query
UPDATE person AS p
INNER JOIN tbl_tmp_audit t ON p.id = t.id
SET status = 'Active';
--second query
SELECT COUNT(*) FROM tbl_tmp_audit;
Drop temporary table tbl_temp_bookings;

Comparing Dates For Multiple Entries

im creating a small hire car system and i want a stored procedure that takes in a date and checks to see which cars are available then. I've got the compare working but if a car has more than one contract and one of the contracts isn't for the entered date but another is it says the car is available. Below is my procedure so far
delimiter //
create procedure allAvailableVehicles(req varchar(15))
BEGIN
select distinct vehicles.vehicleID as "Vehicle ID", vehicles.Make as "Make", vehicles.Model as "Model" from vehicles
left outer join contracts
on vehicles.vehicleID=contracts.vehicleID
where cast(req as date) not between hiredFrom and hiredUntill
or contractID is unknown
order by vehicles.vehicleID;
end
//
delimiter ;
This is a good opportunity to use not exists:
select v.*
from vehicles v
where not exists (select 1
from contracts c
where c.VehicleId = v.VehicleId and
cast(req as date) between hiredFrom and hiredUntil
);
Note: you should not need to cast req as a date, because it should already be stored as a date in the database (unless req also has a time component).
A better way to write the stored procedure is:
delimiter //
create procedure allAvailableVehicles(p_req date)
begin
select v.*
from vehicles v
where not exists (select 1
from contracts c
where c.VehicleId = v.VehicleId and
p_req between hiredFrom and hiredUntil
);
end //
delimiter ;
Use built-in types for date/times. Also, name your parameters to distinguish them from columns.

MYSQL DATABASE create procedure

have a question for you guys,
trying to make a procedure for my mysql table but I need some assistance ...
IM completely block ...
I need to create a procedure that will show the parents name in my table but the table show parents id
ex.
(DELIMITER //
CREATE PROCEDURE fetch_animal_parents (IN animal_id INT, OUT animal_name VARCHAR(10))
BEGIN
DECLARE animal_mom INT DEFAULT 0 ;
DECLARE animal_dad INT DEFAULT 0 ;
DECLARE animal_name_mom VARCHAR(10) ;
DECLARE animal_name_dad VARCHAR(10) ;
SELECT name INTO animal_name, (SELECT name FROM animal WHERE id = child.mother_id) INTO animal_name_mom,
(SELECT name FROM animal WHERE id = child.father_id) INTO animal_name_dad
FROM animal AS child ;
END //)
What im doing wrong ....
................................................................................................
Any input ...
1) why do you select mom/dad's name when you are not using them anywhere?
2) I imagine your procedure should take an child animal id as input and give mom & dad's name as output(that's what you procedure name suggest). In that case you need to either have 2 output value or you need to concatenate those names into 1 variable and return them.
3) #VMai suggested a 2 join format which I would agree. The query will be something like..
SELECT mom.name,dad.name INTO animal_name_mom, animal_name_dad
FROM (select mother_id,father_id from animal where id = <precedure_input>) AS `child`
INNER JOIN (select id,name from animal) AS `mom` ON (mom.id=child.mother_id)
INNER JOIN (select id,name from animal) AS `dad` ON (dad.id=child.father_id)
I see that you have as least tried something on your own (thou very confused). I'd suggest you to start with learning some basic syntax/keyword/functions of mysql before trying procedures. Learn to use GROUP BY, variations of JOIN and you could handle a lot of basic querys.

Result consisted of more than one row Error 1172 mysql

Hello im having a hard time with this stored procedure. im getting the error:
Result consisted of more than one row.
here is my stored procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS `dss`.`COSTRET` $$
CREATE DEFINER=`dwadmin`#`192.168.%.%` PROCEDURE `COSTRET`( TDATE DATE)
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE ls_id VARCHAR(8);
DECLARE ld_cost DECIMAL(10,4);
DECLARE ld_retail DECIMAL(10,4);
DECLARE cur1 CURSOR FOR SELECT DISTINCT `id` FROM `prod_performance` WHERE `psc_week` = TDATE;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
-- Get the Cost
CREATE TEMPORARY TABLE IF NOT EXISTS `prod_itemcost`
SELECT DISTINCTROW `itemcode` ID, `mlist` COST
FROM (SELECT `itemcode`, `pceffdate`, `mlist`
FROM `purchcost` a
where `pceffdate` = (SELECT MAX(z.`pceffdate`) FROM `purchcost` z WHERE z.`itemcode` = a.`itemcode`
AND z.`pceffdate` <= TDATE)) tb
ORDER BY `itemcode`;
OPEN cur1;
REPEAT
FETCH cur1 INTO ls_id;
IF NOT done THEN
SELECT DISTINCTROW `cost` INTO ld_cost FROM `prod_itemcost` WHERE id = ls_id;
UPDATE LOW_PRIORITY `prod_performance` SET `current_cost` = ld_cost WHERE `psc_week` = TDATE and `id` = ls_id;
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
-- Destroy Temporary Tables
DROP TEMPORARY TABLES IF EXISTS `prod_itemcost`;
END $$
DELIMITER ;
Any solutions and recommendations are much appreciated!
I'd say the problem is here :
SELECT DISTINCTROW `cost` INTO ld_cost FROM `prod_itemcost` WHERE id = ls_id;
and caused by this returning more than one row.
How you solve it depends on your requirements. Does the existence of multiple rows imply the database is in need of some cleaning, for example? Or should you be taking the first value of 'cost', or perhaps the sum of all 'cost' for id = ls_id?
Edit :
Your INTO clause is attempting to write multiple rows to a single variable. Looking at your SQL, I'd say the underlying problem is that your initial query to pull back just the latest cost for each ID is being hamstrung by duplicates of pceffdate. If this is the case, this SQL :
SELECT DISTINCTROW `itemcode` ID, `mlist` COST
FROM (SELECT `itemcode`, `pceffdate`, `mlist`
FROM `purchcost` a
where `pceffdate` = (SELECT MAX(z.`pceffdate`) FROM `purchcost` z WHERE z.`itemcode` = a.`itemcode`
AND z.`pceffdate` <= TDATE)) tb
will return more rows than just this :
SELECT DISTINCTROW `itemcode` ID
FROM (SELECT `itemcode`, `pceffdate`, `mlist`
FROM `purchcost` a
where `pceffdate` = (SELECT MAX(z.`pceffdate`) FROM `purchcost` z WHERE z.`itemcode` = a.`itemcode`
AND z.`pceffdate` <= TDATE)) tb
This line
SELECT MAX(z.`pceffdate`) FROM `purchcost` z WHERE z.`itemcode` = a.`itemcode`
AND z.`pceffdate` <= TDATE
has got to be the problem. It must be returning more than 1 row. So, the DBMS is trying to set multiple values to the same thing, which of course it cannot do.
Do you need something else in your WHERE clause there?
The problem is that
SELECT DISTINCTROW `itemcode` ID, `mlist` COST
could store multiple costs against each ID, and so
SELECT DISTINCTROW `cost` INTO ld_cost FROM `prod_itemcost` WHERE id = ls_id;
could return multiple rows for each id.
For example, if purchcost contained the following:
itemcode mlist pceffdate
1 10.99 10-apr-2009
1 11.99 10-apr-2009
1 9.99 09-apr-2009
Then temporary table prod_itemcost would contain:
itemcode mlist
1 10.99
1 11.99
These both being values that were in effect on the most recent pceffdate for that itemcode.
This would then cause a problem with selecting mlist into ld_cost for itemcode 1 because there are two matching values, and the scalar ld_cost can only hold one.
You really need to look at the data in purchcost. If it is possible for 1 item to have more than one entry with different mlist values for the same date/datetime, then you need to decide how that should be handled. Perhaps take the highest value, or the lowest value, or any value. Or perhaps this is an error in the data.
There is another possibility, that is your parameter "TDATE" same as table field name in uppercase or lowercase or mixed. such as 'tdate', 'tDate', 'TDATE'.
so you should check that. I hit this before.
You are inserting an array in a variable instead of a single value that's why its problem occurs.
Like:
DECLARE name varchar;
select f_name into name from student;
here name will accept only single name instead of multiple name;