【问题标题】:Group By not working to calculate amount left in MySqlGroup By 无法计算 MySql 中剩余的数量
【发布时间】:2021-03-14 15:14:54
【问题描述】:

我正在尝试计算交易完成后剩余的库存量,但它返回给我一个负数。我的 GROUP BY 可能有什么问题,因为它似乎不起作用,或者它是实际的计算(如您所知,我是一个完整的初学者)?

    CREATE TABLE items (
    amount int,
    price_for_each int,
    name VARCHAR(20),
    CONSTRAINT PK_items PRIMARY KEY (name)
);
INSERT INTO items (price_for_each, amount, name) VALUES 
(110,22,'2lof milk'),
(99,30,'6 cans of lemonade'),
(150,20,'Pack of butter'),
(450,13,'Roast chicken'),
(99,30,'Pack of rice'),
(20,50,'Banana'),
(200,30,'3kg sugar'),
(150,15,'Toast bread'),
(150,18,'Earl Grey tea');

CREATE TABLE itemsintransactions (
    name VARCHAR(20),
    t_id int,
    amount int,
    FOREIGN KEY (name) REFERENCES items(name),
    FOREIGN KEY (t_id) REFERENCES transactions(t_id)
);
INSERT INTO itemsintransactions (name, t_id, amount) VALUES
('6 cans of lemonade',1,1),
('Roast chicken',1,1),
('Pack of butter',1,1),
('Toast bread',1,1),
('2lof milk',1,2),
('Banana',1,3),
('3kg sugar',1,1),
('6 cans of lemonade',2,5),
('Pack of rice',2,1),
('6 cans of lemonade',3,3),
('Roast chicken',3,2),
('Pack of rice',3,1),
('Pack of butter',3,1),
('2lof milk',4,5),
('Banana',4,20),
('3kg sugar',4,8),
('6 cans of lemonade',5,10),
('Roast chicken',5,10),
('Pack of rice',5,10),
('Pack of butter',5,10),
('Toast bread',5,10),
('2lof milk',5,10),
('Banana',5,10),
('3kg sugar',5,10),
('Earl Grey tea',5,10);

CREATE VIEW ItemsLeft AS
SELECT items.name, (items.amount-sum(itemsintransactions.amount)) AS amount_left
FROM items, itemsintransactions
GROUP BY items.name
ORDER BY items.name;

【问题讨论】:

  • 有什么错误?

标签: mysql sql join


【解决方案1】:

您在FROM items, itemsintransactions 中有一个(notorious and obsolete) comma-join

这是一个问题,因为它使 MySQL 生成并尝试从您的两个表中汇总所有可能的行组合,从而从您的 SUM()s 中产生垃圾。

你想要这个。

FROM items
LEFT JOIN itemsintransactions USING (name)

在这里查看。 https://www.db-fiddle.com/f/mpENTCRM2D7ZcT53V9tNza/0

SELECT items.name, items.amount, 
       SUM(itemsintransactions.amount) taken,
       items.amount - SUM(itemsintransactions.amount) remaining
FROM items
LEFT JOIN itemsintransactions USING (name)
GROUP BY items.name
ORDER BY items.name

使用 LEFT JOIN 代替普通的内部 JOIN 允许来自 items 表的行出现在结果集中,即使它们没有对应的 itemstransactions 条目。

尽管有另一个相反的答案,但您可以在 SELECT 子句中提及 items.amount,因为您按 items.name 分组,这是主键。对于哪个items.amount 值是正确的使用值,没有任何歧义。换句话说,如果您运行此查询 ....

SELECT items.name, ANY_VALUE(items.amount), 
       SUM(itemsintransactions.amount) taken,
       ANY_VALUE(items.amount) - SUM(itemsintransactions.amount) remaining
FROM items
LEFT JOIN itemsintransactions USING (name)
GROUP BY items.name
ORDER BY items.name

你会得到想要的结果。 ANY_VALUE() 从正在聚合的行中选择一些值,在您的情况下,它总是选择正确的值。

【讨论】:

    【解决方案2】:

    首先在itemsintransactions 中聚合,然后将LEFTitems 连接到结果中:

    SELECT i.name, i.amount - COALESCE(t.amount, 0) AS amount_left
    FROM items AS i 
    LEFT JOIN (
      SELECT name, SUM(amount) AS amount
      FROM itemsintransactions 
      GROUP BY name
    ) AS t ON t.name = i.name
    ORDER BY i.name
    

    请参阅demo
    结果:

    > name               | amount_left
    > :----------------- | ----------:
    > 2lof milk          |           5
    > 3kg sugar          |          11
    > 6 cans of lemonade |          11
    > Banana             |          17
    > Earl Grey tea      |           8
    > Pack of butter     |           8
    > Pack of rice       |          18
    > Roast chicken      |           0
    > Toast bread        |           4
    

    【讨论】:

      【解决方案3】:

      下面粗体的items.amount 必须在聚合函数中,因为.amount 字段不在group by 中:

      (items.amount-sum(itemsintransactions.amount))

      【讨论】:

      • 它在什么聚合函数中?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多