【问题标题】:MySQL: Update with join in subqueryMySQL:在子查询中加入更新
【发布时间】:2018-08-15 20:45:54
【问题描述】:

我有一张包含产品的表格和一张包含产品评论的表格。产品表具有父产品和子产品。父产品应该得到子产品的所有评论。我做到了:

DROP TABLE IF EXISTS products;
CREATE TABLE products (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `parent` int(10) unsigned DEFAULT NULL,
    `review` decimal(3,2) DEFAULT NULL,
    PRIMARY KEY(id)
);

DROP TABLE IF EXISTS reviews;
CREATE TABLE reviews (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `product` int(10) unsigned NOT NULL,
    `review` decimal(3,2) DEFAULT NULL,
    PRIMARY KEY(id) 
);

INSERT INTO products SET id=1, parent=null;
INSERT INTO products SET id=2, parent=1;
INSERT INTO products SET id=3, parent=1;

INSERT INTO reviews SET product=2, review=5;
INSERT INTO reviews SET product=3, review=5;
INSERT INTO reviews SET product=3, review=4;

INSERT INTO products SET id=4, parent=null;
INSERT INTO products SET id=5, parent=4;

INSERT INTO reviews SET product=5, review=4;
INSERT INTO reviews SET product=5, review=2;

UPDATE products
SET products.review=
(SELECT SUM(reviews.review)/COUNT(reviews.review) FROM reviews 
LEFT JOIN products p ON p.parent = products.id
)
WHERE products.parent IS NULL;

但是我很惊讶我收到了一个错误:

错误 1054 (42S22):“on 子句”中的未知列“products.id”

关于如何正确执行的任何建议?这个想法是产品 1 应该得到 14/3 = 4.66 的评论,产品 4 应该得到 6/2 = 3 的评论。

【问题讨论】:

  • 我收到错误 1093,而不是 1054。您使用的是什么版本?
  • 感谢您正确提出 SQL 问题(重现您的示例数据库所需的 SQL)
  • 将产品更新为 p1 SET p1.review= (SELECT SUM(reviews.review)/COUNT(reviews.review) FROM reviews where reviews.product = p1.id ) WHERE p1.parent IS NULL;
  • 我正在使用 mysql 版本 5.7.21。

标签: mysql


【解决方案1】:

产品在子查询中不可见。请改用以下语法:

UPDATE products pp
LEFT JOIN (
  SELECT pc.parent, SUM(r.review)/COUNT(r.review) as 'rev'
  FROM reviews r
    LEFT JOIN products pc on r.product = pc.id
  GROUP BY pc.parent
) pcc ON pcc.parent = pp.id  
SET pp.review=pcc.rev
WHERE pp.parent IS NULL;

【讨论】:

    【解决方案2】:

    由于您已将p 声明为products 表的别名,因此您需要在整个查询中使用它。因此,在您的 LEFT JOIN 子句中,只需使用 p.parent 而不是 products.parent

    UPDATE products
    SET products.review=
    (SELECT SUM(reviews.review)/COUNT(reviews.review) FROM reviews 
    LEFT JOIN products p ON p.parent = p.id
    )
    WHERE products.parent IS NULL;
    

    【讨论】:

    • 这不起作用,因为它不会将要更新的产品与子查询中的产品联系起来(=所有产品都会得到相同的评论结果)
    • @slaakso 我认为主题发起者有意简化了他的查询。
    • 请@Werner 澄清一下。此外,示例数据可能包含另一个具有子行的父级。
    • 感谢您的回复。抱歉,我在这个(MySQL 5.7.21)上收到“错误 1093(HY000):您不能在 FROM 子句中指定要更新的目标表 'products'”。
    • @Werner 对我来说工作得很好(MariaDB 10.3)。看起来 MySQL 优化器设置可能是这种类型的 UPDATE..SELECT 查询的问题:stackoverflow.com/questions/45494/…
    【解决方案3】:

    从本质上讲,您似乎在寻找这个值:

    SELECT SUM(r.review)/(SELECT COUNT(*) FROM products) n FROM reviews r;
    +----------+
    | n        |
    +----------+
    | 4.666667 |
    +----------+
    

    所以,类似...

    UPDATE products x 
      JOIN (SELECT SUM(r.review)/(SELECT COUNT(*) FROM products) n FROM reviews r) y
       SET x.review = y.n
     WHERE x.review IS NULL;
    

    【讨论】:

    • 这将对所有行进行相同的计算(无论它是父母还是孩子)。由于从子查询到主 updateadble 表没有连接(除了 x.review 连接,错字?)所有行都将获得相同的值。了解目的是根据每个父母的孩子值进行计算。
    • 感谢您的回复。是的,不幸的是,这对我的示例中的每个产品都给出了 4 的评论。
    • 这仅对每个空值进行审查。
    猜你喜欢
    • 1970-01-01
    • 2011-07-20
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    相关资源
    最近更新 更多