Join Syntax with loop to left table and list to the columns [closed]
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
closed as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua Nov 19 at 14:37
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
closed as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua Nov 19 at 14:37
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
Nov 19 at 8:32
1
See meta.stackoverflow.com/questions/333952/…
– Strawberry
Nov 19 at 8:32
The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
Nov 19 at 8:45
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
Nov 19 at 8:50
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 Nov 19 at 8:30
Moussa
64
64
closed as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua Nov 19 at 14:37
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.
closed as too broad by Strawberry, philipxy, EdChum, Unheilig, Oussema Aroua Nov 19 at 14:37
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
Nov 19 at 8:32
1
See meta.stackoverflow.com/questions/333952/…
– Strawberry
Nov 19 at 8:32
The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
Nov 19 at 8:45
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
Nov 19 at 8:50
add a comment |
2
What have you tried so far?
– Joseph_J
Nov 19 at 8:32
1
See meta.stackoverflow.com/questions/333952/…
– Strawberry
Nov 19 at 8:32
The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
Nov 19 at 8:45
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
Nov 19 at 8:50
2
2
What have you tried so far?
– Joseph_J
Nov 19 at 8:32
What have you tried so far?
– Joseph_J
Nov 19 at 8:32
1
1
See meta.stackoverflow.com/questions/333952/…
– Strawberry
Nov 19 at 8:32
See meta.stackoverflow.com/questions/333952/…
– Strawberry
Nov 19 at 8:32
The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
Nov 19 at 8:45
The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
Nov 19 at 8:45
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
Nov 19 at 8:50
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
Nov 19 at 8:50
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
Nov 19 at 9:42
@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
Nov 19 at 10:07
But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
Nov 19 at 11:02
@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
Nov 19 at 11:32
@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
Nov 19 at 22:25
|
show 6 more comments
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
Nov 19 at 9:42
@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
Nov 19 at 10:07
But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
Nov 19 at 11:02
@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
Nov 19 at 11:32
@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
Nov 19 at 22:25
|
show 6 more comments
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
Nov 19 at 9:42
@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
Nov 19 at 10:07
But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
Nov 19 at 11:02
@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
Nov 19 at 11:32
@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
Nov 19 at 22:25
|
show 6 more comments
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 Nov 20 at 11:26
answered Nov 19 at 9:17
Nick
20.4k51434
20.4k51434
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
Nov 19 at 9:42
@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
Nov 19 at 10:07
But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
Nov 19 at 11:02
@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
Nov 19 at 11:32
@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
Nov 19 at 22:25
|
show 6 more comments
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
Nov 19 at 9:42
@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
Nov 19 at 10:07
But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
Nov 19 at 11:02
@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
Nov 19 at 11:32
@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
Nov 19 at 22:25
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
Nov 19 at 9:42
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
Nov 19 at 9:42
@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
Nov 19 at 10:07
@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
Nov 19 at 10:07
But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
Nov 19 at 11:02
But this doesn't work for mysql database ... syntax problem @Nick
– Moussa
Nov 19 at 11:02
@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
Nov 19 at 11:32
@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
Nov 19 at 11:32
@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
Nov 19 at 22:25
@Moussa did the change help? If not, could you provide more information to help solve the problem?
– Nick
Nov 19 at 22:25
|
show 6 more comments
2
What have you tried so far?
– Joseph_J
Nov 19 at 8:32
1
See meta.stackoverflow.com/questions/333952/…
– Strawberry
Nov 19 at 8:32
The tables warehouse and items seem unnecessary to the question since you aren't using them in desired result?
– P.Salmon
Nov 19 at 8:45
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
Nov 19 at 8:50