【问题标题】:Join Syntax with loop to left table and list to the columns [closed]使用循环连接语法到左表并列出列[关闭]
【发布时间】:2018-11-19 08:30:04
【问题描述】:

我有那 3 张桌子

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

我需要通过在列中列出所有仓库以及数量 结果中显示的每个项目

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 表格仓库和项目似乎对问题没有必要,因为您没有在预期的结果中使用它们?
  • 是的 P.Salmon 在我的查询中我会使用它,但它只是显示表引用的项目 ID 和表引用的仓库 ID。在我的查询中,我会告诉你他们,但为了不让它变得复杂,我使结果变得清晰易懂,以便我得到答案。谢谢

标签: php mysql join


【解决方案1】:

在 MySQL 中实现这一点的唯一实用方法是使用存储过程来构建基于仓库列表的动态查询。查询必须使用条件聚合来构建结果表。对于您的示例数据,构建的查询如下所示:

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

程序如下:

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 ;

以及您的示例数据的输出:

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

Demo on dbfiddle

Alternate demo 展示了使用 5 个仓库的过程。

【讨论】:

  • 如果我有 50 个仓库怎么办? ,我在想的是,如果可以从表仓库中获取所有仓库 id,并使用将这些 id 循环到 itemmovement 的表中并提取结果的语法
  • @Moussa 此程序适用于您拥有的尽可能多的仓库,因为这正是它的作用。这是一个扩展到 3 个仓库的示例:dbfiddle.uk/…
  • 但这不适用于mysql数据库...语法问题@Nick
  • @Moussa 对此感到抱歉 - 我在 MariaDB 上进行了测试,在 PREPARE 语句中使用局部变量没有 MySQL 问题。我已经用一个可以在 MySQL 上编译的版本编辑了我的帖子
  • @Moussa 更改有帮助吗?如果没有,您能否提供更多信息来帮助解决问题?
猜你喜欢
  • 2021-09-16
  • 2018-11-13
  • 1970-01-01
  • 1970-01-01
  • 2021-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多