Sql 中的多表连接

问题描述 投票:0回答:1

我是一个初学者,尝试使用 PHP + SQL 构建非常简单的库存系统
我有2个仓库。我添加了 2 个表,每个仓库 1 个包含 (item id)-(in)-(out) 如下所示

表1

商品编号
项目1 10 0
项目1 5 0
项目2 0 3
项目2 0 2

表2

商品编号
项目1 12 0
项目1 50 0
项目2 0 10
项目2 0 30

我通过使用下面的查询分别显示每个仓库的余额的报告

Select item_id, sum(in-out) as balance from table1 group by item_id

像下面这样

商品编号 平衡
项目1 2
项目2 20

我的问题是如何在一张表中显示每个仓库余额,如下所示

商品编号 仓库1 仓库2
项目1 7 2
项目2 3 20

我厌倦了这个查询,但得到了错误的结果

SELECT table1.item_id, sum(table1.in)-sum(table1.out) as tb1, sum(table2.in)-sum(table2.out) as tb2 FROM table1 , table2 WHERE table1.item_id=table2.item_id GROUP by item_id

上面的查询有2个问题

  1. 结果不正确
  2. 仅显示两个表中的项目,而表中存在但第二个表中不存在的任何项目都不会显示
sql mysql select left-join
1个回答
0
投票

只需计算两个表的总和(就像您对第一个表所做的那样),然后将结果连接到 item_id 上。

如果您可以保证两个仓库都具有完全相同的唯一 item_ids 列表,那么您可以执行 INNER JOIN。我假设它们可能存在一些差异,所以我选择了 FULL JOIN。但是,MySQL 似乎不支持 FULL JOIN 选项。所以我采用了 LEFT JOIN 和 RIGHT JOIN 的 UNION 来达到预期的结果。

我用反引号引用了 IN 和 OUT 列,因为 IN 是 SQL 关键字(不确定 OUT,最好是安全起见)。这样它们将被视为列名,而不是它们的其他含义(即 IN 是一个运算符)。

首先,设置一些表来模拟您的数据。

-- Create table corresponding to warehouse 1
DROP TABLE IF EXISTS warehouse1;
CREATE TABLE warehouse1(item_id CHAR(5) NOT NULL
                    , `in` BIGINT  NOT NULL
                    , `out` BIGINT NOT NULL
                    );
  
INSERT INTO warehouse1(item_id
                    , `in`
                    , `out`
                    )
VALUES('item1', 10, 0)
    , ('item1', 5, 0)
    , ('item2', 0, 3)
    , ('item2', 0, 2);

-- Create table corresponding to warehouse 2
CREATE TABLE warehouse2(item_id CHAR(5) NOT NULL
                    , `in` BIGINT  NOT NULL
                    , `out` BIGINT NOT NULL
                    );
                    
INSERT INTO warehouse2(item_id
                    , `in`
                    , `out`
                    )
VALUES('item1', 12, 0)
    , ('item1', 50, 0)
    , ('item2', 0, 10)
    , ('item2', 0, 30);

其次,执行聚合并连接结果。

-- Compute the sums for each table, grouped by the item_id and join them together
-- We want a FULL JOIN here. But MySQL doesn't support it, so we UNION a LEFT and a RIGHT
-- to get the same effect.
SELECT wh1.item_id AS item_id
    , wh1.balance AS warehouse1_balance
    , wh2.balance AS warehouse2_balance
FROM(
    SELECT item_id
        , SUM(`in` - `out`) AS balance
    FROM warehouse1
    GROUP BY item_id
    ) wh1
LEFT JOIN (
    SELECT item_id
        , SUM(`in` - `out`) AS balance
    FROM warehouse2
    GROUP BY item_id
    ) wh2
    ON wh1.item_id = wh2.item_id

UNION

SELECT wh2.item_id AS item_id
    , wh1.balance AS warehouse1_balance
    , wh2.balance AS warehouse2_balance
FROM(
    SELECT item_id
        , SUM(`in` - `out`) AS balance
    FROM warehouse1
    GROUP BY item_id
    ) wh1
RIGHT JOIN (
    SELECT item_id
        , SUM(`in` - `out`) AS balance
    FROM warehouse2
    GROUP BY item_id
    ) wh2
    ON wh1.item_id = wh2.item_id
;

我故意使用 UNION 而不是 UNION ALL,因为 LEFT JOIN 和 RIGHT JOIN 都将包含 INNER JOIN。所以我们不想包含两次 INNER JOIN。

自己尝试一下:db<>fiddle

© www.soinside.com 2019 - 2024. All rights reserved.