How to reverse the results of this procedure? - mysql

I am tring to create a simple database for a hotel. It is supposed to take care of all bookings. I am tring to make a procedure which will search for not booked rooms in given date. However, as for now my procedure can show room numbers which already have been booked at some point. Only first 5 of 20 rooms were booked so far, and they appear, the other do not.
Can anyone give me any ideas what is wrong or even better, how to make the whole procedure work?
These are the important tables
This is the call:
The results should go all the way up to "NumerPokoju" = 20, but they stop, because they are not in the Bookings table
To clarify the question: I want the procedure to show also the rooms that simple were never booked, not only the ones that have been at least once.
DELIMITER //
CREATE PROCEDURE freeRooms(IN ilosc int, IN poczatek date, IN koniec date)
BEGIN
SELECT Rooms.RoomID AS "Numer pokoju", Rooms.Places AS "Ilosc lozek"
FROM Rooms INNER JOIN Bookings ON Rooms.RoomID = Bookings.RoomID
WHERE ((poczatek < Bookings.ArrDate AND koniec < Bookings.ArrDate) OR ((poczatek > Bookings.DepDate) AND (koniec > Bookings.DepDate)))
AND ilosc <= Rooms.Places;
END //
DELIMITER ;

Use NOT EXISTS instead of the join:
SELECT
r.RoomID AS "Numer pokoju",
r.Places AS "Ilosc lozek"
FROM Rooms r
WHERE
NOT EXISTS (
SELECT 1 FROM Bookings
WHERE
RoomID = r.RoomID
AND (
poczatek BEWEEN ArrDate AND DepDate
OR
koniec BEWEEN ArrDate AND DepDate
)
)
AND
ilosc <= r.Places;
I'm not sure about the last condition: ilosc <= r.Places if and why you need it.

Related

MySQL Stored procedure to combine multiple select and update

I am newbie to stored procedure, hence this basic question.
I want to create a table of average sales for last 10 days, then I need to query existing stock and update the stock in the sales table.
This create sales data for last 10 days.
DELIMITER //
CREATE PROCEDURE JDSTOCK()
BEGIN
DROP TABLE IF EXISTS Test1;
Create table Test1 AS
Select
Invoice.BranchID,
Invoice.CustomerName,
InvoiceDetail.ProductMasterID,
Sum(InvoiceDetail.Quantity),
Avg(InvoiceDetail.Quantity) As Avg_Quantity,
0.00 As BranchStock
From
Invoice Inner Join
InvoiceDetail On InvoiceDetail.InvoiceID = Invoice.InvoiceID
Where
Invoice.InvoiceDate >= CurDate() - 10 And
Invoice.CustomerName Like '%BRANCH%'
Group By
Invoice.BranchID,
Invoice.CustomerName,
InvoiceDetail.ProductMasterID ;
END;//
DELIMITER;
2. Step that I want to execute from stored procedure
* Create Stock Table for KTMY */
Select
Stock.BranchID,
Stock.ProductMasterID,
Sum(Stock.CurrentQty) As Sum_CurrentQty,
Branch.BranchName,
Max(Stock.PurchaseDate) As Max_PurchaseDate
From
Stock Inner Join
Branch On Branch.BranchID = Stock.BranchID
Where
Branch.BranchName = 'KTMY'
Group By
Stock.BranchID,
Stock.ProductMasterID,
Branch.BranchName
Having
Sum(Stock.CurrentQty) > 0
3. Third step
*** Update stock in sales table
Update DevTest INNER JOIN DevStock on
DevTest.ProductMasterID = DevStock.ProductMasterID
SET DevTest.EKMStock = DevStock.Sum_CurrentQty;
How will I achieve this in stored procedure.
Thanks in advance.

Stored Procedure with Pivot Does Not Return Result Structure but Zero Value

MyActualresultI am trying to get count of data which have particular status on different dates. Something like tracking shipment and getting today's report.
I have used Pivot with stored procedure. I get result as column and rows but return value null on executing the Sp.
Can any one please suggests how can I rectify the issue?
I tried to put the query in some variable and then execute but its not done correctly.
Create PROCEDURE [dbo].[GetCountOfShipmentWithStatus]
#DateToStart Date,
#DateToEnd Date,
#LabName nvarchar(30)
AS
BEGIN
SET NOCOUNT ON;
WITH TrackShipment AS
(
SELECT exData.ID, CAST(ExpectedDeliveryDt AS DATE) AS Deliverydate,A.AccountCode,L.Name, DATENAME(dw, ExpectedDeliveryDt) AS DayOfWeek,exData.MileStoneTypeId AS TrackingStatus,exData.AccountNo
FROM [Tracking].[TrackingExternalData] exData
Left Join [systemManagement].[SystemMetaData] sysmetadat on exdata.MileStoneTypeId=sysmetadat.systemMetaDataId
Left Join [Data_Replication_EZSHIP].[dbo].[AccountNumber] AS A on exData.AccountNo=A.AccountCode
Left JOIN [Data_Replication_EZSHIP].[dbo].[Location] AS L ON A.LocationId = L.Id
WHERE L.Name=#LabName
AND sysmetadat.systemMetaDataId IN ('E770CE7C-E0E6-40C6-AC51-5D2129F2DEB7','D6A011C8-C39C-45B5-9127-52D20C68E1C3','C7657AE1-9354-E911-BB4A-005056B00B08','559ECEC2-969A-4F8C-9A95-21C613D82F3A')
AND exData.ExpectedDeliveryDt <= #DateToStart AND exData.ExpectedDeliveryDt >= #DateToEnd
)
SELECT Deliverydate, DayOfWeek,
-- List of Pivoted Columns
[E770CE7C-E0E6-40C6-AC51-5D2129F2DEB7],[D6A011C8-C39C-45B5-9127-52D20C68E1C3], [C7657AE1-9354-E911-BB4A-005056B00B08], [559ECEC2-969A-4F8C-9A95-21C613D82F3A]
FROM TrackShipment
PIVOT
(
COUNT(Id)
-- List of Pivoted columns
FOR TrackingStatus IN([E770CE7C-E0E6-40C6-AC51-5D2129F2DEB7],[D6A011C8-C39C-45B5-9127-52D20C68E1C3], [C7657AE1-9354-E911-BB4A-005056B00B08], [559ECEC2-969A-4F8C-9A95-21C613D82F3A])
) as pvt
ORDER BY Deliverydate DESC
END
GO
I expect return value same as result of pivot.
I am guessing that this condition is incorrect:
exData.ExpectedDeliveryDt <= #DateToStart AND
exData.ExpectedDeliveryDt >= #DateToEnd
I don't know what you intend, because you haven't provided sample data, desired results, or an explanation of the logic you want.
But I am guessing that the comparison are backwards:
exData.ExpectedDeliveryDt >= #DateToStart AND
exData.ExpectedDeliveryDt <= #DateToEnd

Updating 180k rows via MySQL stored procedure & function is too slow - how to speed up

I have the following stored procedure:
CREATE DEFINER=`ST`#`%` PROCEDURE `CalculateCheapestPriceALL`()
BEGIN
UPDATE
tickets
SET
tickets.Cheapest = GetCheapestTicket(tickets.STPerformerID, tickets.STVenueID, tickets.FeedID);
END
The function GetCheapestTicket is as follows:
CREATE DEFINER=`suprtickets`#`%` FUNCTION `GetCheapestTicket`(performerID INT(11), venueID INT(11), feedID INT(11)) RETURNS decimal(10,2)
BEGIN
DECLARE TicketPrice DECIMAL(10,2);
SET TicketPrice =
IFNULL((
SELECT
MIN(tickets.Price)
FROM
tickets
WHERE
tickets.STPerformerID = performerID
AND
tickets.STVenueID = venueID
AND
tickets.FeedID = feedID
AND
tickets.Price > 0
),0);
RETURN TicketPrice;
END
Running the stored procedure currently takes about 10 minutes, and I'm looking for ways to speed this up.
The following image shows a sample of the data:
The idea behind the stored procedure is to find the cheapest price for the same STPerformerID and STVenueID, and then update this in the Cheapest column. So then I can quickly look up the lowest price for each peformer and venue.
There are about 20k individual Perfomers, and a similar amount of Venues.
Thanks for your help.
Your basic problem is that you are running the query to find the lowest price over again for every row, which is very inefficient.
If you combine the two queries into one query. it will execute significantly faster:
UPDATE tickets AS t1
JOIN (SELECT STPerformerID, STVenueID, STFeedID, MIN(Price) AS cheapest
FROM tickets
WHERE Price > 0
GROUP BY STPerformerID, STVenueID, STFeedID) AS t2
USING (STPerformerID, STVenueID, STFeedID)
SET t1.Price = t2.cheapest
To make it perform well, make sure you have a composite index on (STPerformerID, STVenueID, STFeedID) (or at least some subset of these columns).

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.

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;