I have a query, I have a problem where I have a table package and another bins, where package has 100000 (the structure is described below) in this table there is a field called wheitgh which has an int random value from 0 to a maximum of 100 and in the other table bins is a container so I have to accommodate all the packages of different sizes in bins containers, with the premise that it is the smallest amount of containers, the following code works for me up to 1000 packages without problem, but when I increase the number the query does not finish but to process, and I have no idea what can be! Greetings!
/ CREATE TABLE packages (ID int Primary Key, Weight int NOT NULL, BinNo int); CREATE TABLE Bins (BinNo int Primary Key, SpaceLeft int); /
CREATE OR REPLACE FUNCTION poblate_tables () RETURNS integer AS $ BODY $ declare - _i integer: = 0;
_packageQuantity integer := 0;
_packageMaxQuantity integer := 10000;
_binsQuantity integer := 0;
_binsMaxQuantity integer := 20000;
_maxPackageWeight integer := 0;
begin
LOOP
_packageQuantity = _packageQuantity + 1;
INSERT INTO Packages(ID, Weight) VALUES (_packageQuantity, random());
IF _packageQuantity = _packageMaxQuantity THEN
EXIT; -- exit loop
END IF;
END LOOP;
SELECT MAX(Weight) into _maxPackageWeight FROM Packages;
WHILE _binsQuantity < _binsMaxQuantity
LOOP
_binsQuantity = _binsQuantity + 1;
INSERT INTO Bins(BinNo, SpaceLeft) VALUES (_binsQuantity, random()+_maxPackageWeight);
END LOOP;
return 1;
end; $ BODY $ LANGUAGE 'plpgsql' VOLATILE;
CREATE OR REPLACE FUNCTION locate_package () RETURNS integer AS $ BODY $
DECLARE
_binId integer;
_binSpace integer;
_packageID integer;
_packageWeight integer;
_rs record;
BEGIN for _rs in SELECT ID, Weight FROM Packages WHERE BinNo is null ORDER BY Weight DESC / Runs all packages that do not have an assigned container // Order first those that have the most weight because it is easier to find a container when they are less busy // As you go around you assign a container to each one, if you find // I assume that the space of the container is related to the weight and not to the unit of the package. For example, a container with SpaceLeft = 200 can save two packages of 100kg / LOOP
_packageID = _rs.ID; -- id del paquete que quiero ubicar
_packageWeight = _rs.Weight; -- peso del paquete que quiero ubicar
--Obtiene un Contenedor de aquellos contenedores que ya contienen paquetes para evitar usar uno nuevo
SELECT bi.BinNo, bi.SpaceLeft
into _binId, _binSpace
FROM Bins bi
JOIN Packages pk ON bi.BinNo = pk.BinNo
WHERE SpaceLeft >= _packageWeight
GROUP BY bi.BinNo, bi.SpaceLeft
ORDER BY SpaceLeft DESC
LIMIT 1;
if _binId is null --Si no encontro contenedor en la consulta anterior busca uno nuevo
THEN
SELECT bi.BinNo, bi.SpaceLeft
into _binId, _binSpace
FROM Bins bi
WHERE SpaceLeft >= _packageWeight
ORDER BY SpaceLeft DESC
LIMIT 1;
END IF;
if _binId is not null
THEN
--actualizo el paquete para asignar el id de contenedor encontrado
UPDATE Packages SET BinNo = _binId WHERE ID = _packageID;
--actualizo el espacio disponible del contenedor restando lo ocupado por el nuevo paquete
UPDATE Bins SET SpaceLeft = _binSpace - _packageWeight WHERE BinNo = _binId;
END IF;
END LOOP;
RETURN 1; end; $ BODY $ LANGUAGE 'plpgsql' VOLATILE;
select poblate_tables (); select locate_package (); - SELECT * FROM packages; - SELECT * FROM bins;