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
php mysql join
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.
add a comment |
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
php mysql join
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
add a comment |
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
php mysql join
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
php mysql join
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
add a comment |
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
add a comment |
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.
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
add a comment |
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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