Join Syntax with loop to left table and list to the columns [on hold]











up vote
-3
down vote

favorite












I have those 3 tables



Warehouse

Id name
1 Warehouse 1
2 Warehouse 2


Items

Id description
1 Item 1
2 Item 2
3 Item 3



itemmovement

itemid qtyin qtyout warehouseid
1 2 1
1 1 1
1 2 2
2 1 1
2 3 1
2 1 1
2 1 2


Result
ItemId SumQuantityWarehouse1 SumQuantityWarehouse2
1 1 2
2 3 1
3 0 0


I need the result to sum up sum(qtyin)-sum(qtyout) with respect to itemid and warehouseid , by listing all the warehouses in columns with the quantities
of each item as shown in the result










share|improve this question













put on hold as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua 14 hours ago


Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.











  • 2




    What have you tried so far?
    – Joseph_J
    20 hours ago






  • 1




    See meta.stackoverflow.com/questions/333952/…
    – Strawberry
    20 hours ago










  • The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
    – P.Salmon
    20 hours ago










  • Yes P.Salmon in my query i will use it but it is just to show the item id to which table refers and the warehouseid to which table refers . in my query i will you them , but not to make it complicated i made the result to be clear and easy so that i can get an answer. thank you
    – Moussa
    19 hours ago















up vote
-3
down vote

favorite












I have those 3 tables



Warehouse

Id name
1 Warehouse 1
2 Warehouse 2


Items

Id description
1 Item 1
2 Item 2
3 Item 3



itemmovement

itemid qtyin qtyout warehouseid
1 2 1
1 1 1
1 2 2
2 1 1
2 3 1
2 1 1
2 1 2


Result
ItemId SumQuantityWarehouse1 SumQuantityWarehouse2
1 1 2
2 3 1
3 0 0


I need the result to sum up sum(qtyin)-sum(qtyout) with respect to itemid and warehouseid , by listing all the warehouses in columns with the quantities
of each item as shown in the result










share|improve this question













put on hold as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua 14 hours ago


Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.











  • 2




    What have you tried so far?
    – Joseph_J
    20 hours ago






  • 1




    See meta.stackoverflow.com/questions/333952/…
    – Strawberry
    20 hours ago










  • The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
    – P.Salmon
    20 hours ago










  • Yes P.Salmon in my query i will use it but it is just to show the item id to which table refers and the warehouseid to which table refers . in my query i will you them , but not to make it complicated i made the result to be clear and easy so that i can get an answer. thank you
    – Moussa
    19 hours ago













up vote
-3
down vote

favorite









up vote
-3
down vote

favorite











I have those 3 tables



Warehouse

Id name
1 Warehouse 1
2 Warehouse 2


Items

Id description
1 Item 1
2 Item 2
3 Item 3



itemmovement

itemid qtyin qtyout warehouseid
1 2 1
1 1 1
1 2 2
2 1 1
2 3 1
2 1 1
2 1 2


Result
ItemId SumQuantityWarehouse1 SumQuantityWarehouse2
1 1 2
2 3 1
3 0 0


I need the result to sum up sum(qtyin)-sum(qtyout) with respect to itemid and warehouseid , by listing all the warehouses in columns with the quantities
of each item as shown in the result










share|improve this question













I have those 3 tables



Warehouse

Id name
1 Warehouse 1
2 Warehouse 2


Items

Id description
1 Item 1
2 Item 2
3 Item 3



itemmovement

itemid qtyin qtyout warehouseid
1 2 1
1 1 1
1 2 2
2 1 1
2 3 1
2 1 1
2 1 2


Result
ItemId SumQuantityWarehouse1 SumQuantityWarehouse2
1 1 2
2 3 1
3 0 0


I need the result to sum up sum(qtyin)-sum(qtyout) with respect to itemid and warehouseid , by listing all the warehouses in columns with the quantities
of each item as shown in the result







php mysql join






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 20 hours ago









Moussa

84




84




put on hold as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua 14 hours ago


Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.






put on hold as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua 14 hours ago


Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.










  • 2




    What have you tried so far?
    – Joseph_J
    20 hours ago






  • 1




    See meta.stackoverflow.com/questions/333952/…
    – Strawberry
    20 hours ago










  • The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
    – P.Salmon
    20 hours ago










  • Yes P.Salmon in my query i will use it but it is just to show the item id to which table refers and the warehouseid to which table refers . in my query i will you them , but not to make it complicated i made the result to be clear and easy so that i can get an answer. thank you
    – Moussa
    19 hours ago














  • 2




    What have you tried so far?
    – Joseph_J
    20 hours ago






  • 1




    See meta.stackoverflow.com/questions/333952/…
    – Strawberry
    20 hours ago










  • The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
    – P.Salmon
    20 hours ago










  • Yes P.Salmon in my query i will use it but it is just to show the item id to which table refers and the warehouseid to which table refers . in my query i will you them , but not to make it complicated i made the result to be clear and easy so that i can get an answer. thank you
    – Moussa
    19 hours ago








2




2




What have you tried so far?
– Joseph_J
20 hours ago




What have you tried so far?
– Joseph_J
20 hours ago




1




1




See meta.stackoverflow.com/questions/333952/…
– Strawberry
20 hours ago




See meta.stackoverflow.com/questions/333952/…
– Strawberry
20 hours ago












The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
20 hours ago




The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
20 hours ago












Yes P.Salmon in my query i will use it but it is just to show the item id to which table refers and the warehouseid to which table refers . in my query i will you them , but not to make it complicated i made the result to be clear and easy so that i can get an answer. thank you
– Moussa
19 hours ago




Yes P.Salmon in my query i will use it but it is just to show the item id to which table refers and the warehouseid to which table refers . in my query i will you them , but not to make it complicated i made the result to be clear and easy so that i can get an answer. thank you
– Moussa
19 hours ago












1 Answer
1






active

oldest

votes

















up vote
1
down vote













The only practical way to achieve this in MySQL is by using a stored procedure to build a dynamic query based on the list of warehouses. The query has to use conditional aggregation to build the result table. For your sample data, the query that is built looks like this:



SELECT i.Id
, SUM(CASE WHEN m.warehouseID=1 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 1`
, SUM(CASE WHEN m.warehouseID=2 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 2`
FROM items i
LEFT JOIN itemmovement m ON m.itemid = i.Id
GROUP BY Id


Here is the procedure:



DELIMITER //
DROP PROCEDURE IF EXISTS stocktake //
CREATE PROCEDURE stocktake()
BEGIN
DECLARE wid INT;
DECLARE wname VARCHAR(20);
DECLARE query TEXT DEFAULT '';
DECLARE finished INT DEFAULT 0;
DECLARE whouse_cursor CURSOR FOR SELECT Id, name FROM warehouse;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN whouse_cursor;
SET @query = 'SELECT i.Id';
get_whouse: LOOP
FETCH whouse_cursor INTO wid, wname;
IF finished = 1 THEN
LEAVE get_whouse;
END IF;
SET @query = CONCAT(@query, ', SUM(CASE WHEN m.warehouseID=', wid, ' THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `', wname, '`');
END LOOP get_whouse;
SET @query = CONCAT(@query, ' FROM items i LEFT JOIN itemmovement m ON m.itemid = i.Id');
SET @query = CONCAT(@query, ' GROUP BY Id');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;


And the output for your sample data:



Id  Warehouse 1     Warehouse 2
1 1 2
2 3 1
3 0 0


Demo on dbfiddle



Alternate demo showing the procedure working with 5 warehouses.






share|improve this answer























  • What if i have 50 warehouses ? , what i'm thinking of is that if it is possible to get all the warehouse id from the table warehouse , and use a syntax that loops through those id's into the table of the itemmovement and extract the result
    – Moussa
    19 hours ago










  • @Moussa this procedure will work for as many warehouses as you have because that's exactly what it does. Here's an example with it expanded to 3 warehouses: dbfiddle.uk/…
    – Nick
    18 hours ago










  • But this doesn't work for mysql database ... syntax problem @Nick
    – Moussa
    17 hours ago












  • @Moussa sorry about that - I tested on MariaDB which doesn't have MySQLs problem with using local variables in PREPARE statements. I've edited my post with a version that will compile on MySQL too
    – Nick
    17 hours ago










  • @Moussa did the change help? If not, could you provide more information to help solve the problem?
    – Nick
    6 hours ago


















1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote













The only practical way to achieve this in MySQL is by using a stored procedure to build a dynamic query based on the list of warehouses. The query has to use conditional aggregation to build the result table. For your sample data, the query that is built looks like this:



SELECT i.Id
, SUM(CASE WHEN m.warehouseID=1 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 1`
, SUM(CASE WHEN m.warehouseID=2 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 2`
FROM items i
LEFT JOIN itemmovement m ON m.itemid = i.Id
GROUP BY Id


Here is the procedure:



DELIMITER //
DROP PROCEDURE IF EXISTS stocktake //
CREATE PROCEDURE stocktake()
BEGIN
DECLARE wid INT;
DECLARE wname VARCHAR(20);
DECLARE query TEXT DEFAULT '';
DECLARE finished INT DEFAULT 0;
DECLARE whouse_cursor CURSOR FOR SELECT Id, name FROM warehouse;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN whouse_cursor;
SET @query = 'SELECT i.Id';
get_whouse: LOOP
FETCH whouse_cursor INTO wid, wname;
IF finished = 1 THEN
LEAVE get_whouse;
END IF;
SET @query = CONCAT(@query, ', SUM(CASE WHEN m.warehouseID=', wid, ' THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `', wname, '`');
END LOOP get_whouse;
SET @query = CONCAT(@query, ' FROM items i LEFT JOIN itemmovement m ON m.itemid = i.Id');
SET @query = CONCAT(@query, ' GROUP BY Id');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;


And the output for your sample data:



Id  Warehouse 1     Warehouse 2
1 1 2
2 3 1
3 0 0


Demo on dbfiddle



Alternate demo showing the procedure working with 5 warehouses.






share|improve this answer























  • What if i have 50 warehouses ? , what i'm thinking of is that if it is possible to get all the warehouse id from the table warehouse , and use a syntax that loops through those id's into the table of the itemmovement and extract the result
    – Moussa
    19 hours ago










  • @Moussa this procedure will work for as many warehouses as you have because that's exactly what it does. Here's an example with it expanded to 3 warehouses: dbfiddle.uk/…
    – Nick
    18 hours ago










  • But this doesn't work for mysql database ... syntax problem @Nick
    – Moussa
    17 hours ago












  • @Moussa sorry about that - I tested on MariaDB which doesn't have MySQLs problem with using local variables in PREPARE statements. I've edited my post with a version that will compile on MySQL too
    – Nick
    17 hours ago










  • @Moussa did the change help? If not, could you provide more information to help solve the problem?
    – Nick
    6 hours ago















up vote
1
down vote













The only practical way to achieve this in MySQL is by using a stored procedure to build a dynamic query based on the list of warehouses. The query has to use conditional aggregation to build the result table. For your sample data, the query that is built looks like this:



SELECT i.Id
, SUM(CASE WHEN m.warehouseID=1 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 1`
, SUM(CASE WHEN m.warehouseID=2 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 2`
FROM items i
LEFT JOIN itemmovement m ON m.itemid = i.Id
GROUP BY Id


Here is the procedure:



DELIMITER //
DROP PROCEDURE IF EXISTS stocktake //
CREATE PROCEDURE stocktake()
BEGIN
DECLARE wid INT;
DECLARE wname VARCHAR(20);
DECLARE query TEXT DEFAULT '';
DECLARE finished INT DEFAULT 0;
DECLARE whouse_cursor CURSOR FOR SELECT Id, name FROM warehouse;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN whouse_cursor;
SET @query = 'SELECT i.Id';
get_whouse: LOOP
FETCH whouse_cursor INTO wid, wname;
IF finished = 1 THEN
LEAVE get_whouse;
END IF;
SET @query = CONCAT(@query, ', SUM(CASE WHEN m.warehouseID=', wid, ' THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `', wname, '`');
END LOOP get_whouse;
SET @query = CONCAT(@query, ' FROM items i LEFT JOIN itemmovement m ON m.itemid = i.Id');
SET @query = CONCAT(@query, ' GROUP BY Id');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;


And the output for your sample data:



Id  Warehouse 1     Warehouse 2
1 1 2
2 3 1
3 0 0


Demo on dbfiddle



Alternate demo showing the procedure working with 5 warehouses.






share|improve this answer























  • What if i have 50 warehouses ? , what i'm thinking of is that if it is possible to get all the warehouse id from the table warehouse , and use a syntax that loops through those id's into the table of the itemmovement and extract the result
    – Moussa
    19 hours ago










  • @Moussa this procedure will work for as many warehouses as you have because that's exactly what it does. Here's an example with it expanded to 3 warehouses: dbfiddle.uk/…
    – Nick
    18 hours ago










  • But this doesn't work for mysql database ... syntax problem @Nick
    – Moussa
    17 hours ago












  • @Moussa sorry about that - I tested on MariaDB which doesn't have MySQLs problem with using local variables in PREPARE statements. I've edited my post with a version that will compile on MySQL too
    – Nick
    17 hours ago










  • @Moussa did the change help? If not, could you provide more information to help solve the problem?
    – Nick
    6 hours ago













up vote
1
down vote










up vote
1
down vote









The only practical way to achieve this in MySQL is by using a stored procedure to build a dynamic query based on the list of warehouses. The query has to use conditional aggregation to build the result table. For your sample data, the query that is built looks like this:



SELECT i.Id
, SUM(CASE WHEN m.warehouseID=1 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 1`
, SUM(CASE WHEN m.warehouseID=2 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 2`
FROM items i
LEFT JOIN itemmovement m ON m.itemid = i.Id
GROUP BY Id


Here is the procedure:



DELIMITER //
DROP PROCEDURE IF EXISTS stocktake //
CREATE PROCEDURE stocktake()
BEGIN
DECLARE wid INT;
DECLARE wname VARCHAR(20);
DECLARE query TEXT DEFAULT '';
DECLARE finished INT DEFAULT 0;
DECLARE whouse_cursor CURSOR FOR SELECT Id, name FROM warehouse;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN whouse_cursor;
SET @query = 'SELECT i.Id';
get_whouse: LOOP
FETCH whouse_cursor INTO wid, wname;
IF finished = 1 THEN
LEAVE get_whouse;
END IF;
SET @query = CONCAT(@query, ', SUM(CASE WHEN m.warehouseID=', wid, ' THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `', wname, '`');
END LOOP get_whouse;
SET @query = CONCAT(@query, ' FROM items i LEFT JOIN itemmovement m ON m.itemid = i.Id');
SET @query = CONCAT(@query, ' GROUP BY Id');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;


And the output for your sample data:



Id  Warehouse 1     Warehouse 2
1 1 2
2 3 1
3 0 0


Demo on dbfiddle



Alternate demo showing the procedure working with 5 warehouses.






share|improve this answer














The only practical way to achieve this in MySQL is by using a stored procedure to build a dynamic query based on the list of warehouses. The query has to use conditional aggregation to build the result table. For your sample data, the query that is built looks like this:



SELECT i.Id
, SUM(CASE WHEN m.warehouseID=1 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 1`
, SUM(CASE WHEN m.warehouseID=2 THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `SUMWarehouse 2`
FROM items i
LEFT JOIN itemmovement m ON m.itemid = i.Id
GROUP BY Id


Here is the procedure:



DELIMITER //
DROP PROCEDURE IF EXISTS stocktake //
CREATE PROCEDURE stocktake()
BEGIN
DECLARE wid INT;
DECLARE wname VARCHAR(20);
DECLARE query TEXT DEFAULT '';
DECLARE finished INT DEFAULT 0;
DECLARE whouse_cursor CURSOR FOR SELECT Id, name FROM warehouse;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN whouse_cursor;
SET @query = 'SELECT i.Id';
get_whouse: LOOP
FETCH whouse_cursor INTO wid, wname;
IF finished = 1 THEN
LEAVE get_whouse;
END IF;
SET @query = CONCAT(@query, ', SUM(CASE WHEN m.warehouseID=', wid, ' THEN COALESCE(m.qtyin, 0) - COALESCE(m.qtyout, 0) ELSE 0 END) AS `', wname, '`');
END LOOP get_whouse;
SET @query = CONCAT(@query, ' FROM items i LEFT JOIN itemmovement m ON m.itemid = i.Id');
SET @query = CONCAT(@query, ' GROUP BY Id');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;


And the output for your sample data:



Id  Warehouse 1     Warehouse 2
1 1 2
2 3 1
3 0 0


Demo on dbfiddle



Alternate demo showing the procedure working with 5 warehouses.







share|improve this answer














share|improve this answer



share|improve this answer








edited 6 hours ago

























answered 19 hours ago









Nick

18.8k41433




18.8k41433












  • What if i have 50 warehouses ? , what i'm thinking of is that if it is possible to get all the warehouse id from the table warehouse , and use a syntax that loops through those id's into the table of the itemmovement and extract the result
    – Moussa
    19 hours ago










  • @Moussa this procedure will work for as many warehouses as you have because that's exactly what it does. Here's an example with it expanded to 3 warehouses: dbfiddle.uk/…
    – Nick
    18 hours ago










  • But this doesn't work for mysql database ... syntax problem @Nick
    – Moussa
    17 hours ago












  • @Moussa sorry about that - I tested on MariaDB which doesn't have MySQLs problem with using local variables in PREPARE statements. I've edited my post with a version that will compile on MySQL too
    – Nick
    17 hours ago










  • @Moussa did the change help? If not, could you provide more information to help solve the problem?
    – Nick
    6 hours ago


















  • What if i have 50 warehouses ? , what i'm thinking of is that if it is possible to get all the warehouse id from the table warehouse , and use a syntax that loops through those id's into the table of the itemmovement and extract the result
    – Moussa
    19 hours ago










  • @Moussa this procedure will work for as many warehouses as you have because that's exactly what it does. Here's an example with it expanded to 3 warehouses: dbfiddle.uk/…
    – Nick
    18 hours ago










  • But this doesn't work for mysql database ... syntax problem @Nick
    – Moussa
    17 hours ago












  • @Moussa sorry about that - I tested on MariaDB which doesn't have MySQLs problem with using local variables in PREPARE statements. I've edited my post with a version that will compile on MySQL too
    – Nick
    17 hours ago










  • @Moussa did the change help? If not, could you provide more information to help solve the problem?
    – Nick
    6 hours ago
















What if i have 50 warehouses ? , what i'm thinking of is that if it is possible to get all the warehouse id from the table warehouse , and use a syntax that loops through those id's into the table of the itemmovement and extract the result
– Moussa
19 hours ago




What if i have 50 warehouses ? , what i'm thinking of is that if it is possible to get all the warehouse id from the table warehouse , and use a syntax that loops through those id's into the table of the itemmovement and extract the result
– Moussa
19 hours ago












@Moussa this procedure will work for as many warehouses as you have because that's exactly what it does. Here's an example with it expanded to 3 warehouses: dbfiddle.uk/…
– Nick
18 hours ago




@Moussa this procedure will work for as many warehouses as you have because that's exactly what it does. Here's an example with it expanded to 3 warehouses: dbfiddle.uk/…
– Nick
18 hours ago












But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
17 hours ago






But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
17 hours ago














@Moussa sorry about that - I tested on MariaDB which doesn't have MySQLs problem with using local variables in PREPARE statements. I've edited my post with a version that will compile on MySQL too
– Nick
17 hours ago




@Moussa sorry about that - I tested on MariaDB which doesn't have MySQLs problem with using local variables in PREPARE statements. I've edited my post with a version that will compile on MySQL too
– Nick
17 hours ago












@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
6 hours ago




@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
6 hours ago



Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

Refactoring coordinates for Minecraft Pi buildings written in Python