我的问题是我想从两个表中删除记录,删除以下查询结果的记录:
SELECT AVG(pr.rating) AS rating_average
FROM products p
INNER JOIN product_ratings pr
ON pr.product_id = p.product_id
GROUP BY p.product_id
HAVING AVG(pr.rating) < 3
以上查询显示的产品平均评分小于3,我想删除上述查询中所有结果的产品及其相关评级。
我查看了DELETE FROM product_ratings, products WHERE EXISTS (//above query)
,但这不起作用,我一直在尝试各种DELETE语句无济于事。
我已阅读以下内容,仍无法找到解决方案:SQL: DELETE Statement&amp; SQL: EXISTS Condition
表格为products
和product_ratings
,结构如下:
products
--------
product_id [PK] | link | ...
product_ratings
---------------
rating_id [PK] | rating | product_id
感谢任何帮助,以及参考资料的链接,以便更好地了解它是如何完成的。
编辑:抱歉没有说明我正在使用的RDBMS,它是MySQLEDIT2:现在有点困惑,@ Martin的例子不像其他答案那样使用临时表,我认为这是因为我的模糊问题没有说明我正在使用的RDBMS?
答案 0 :(得分:2)
您应该在表之间创建一个带有引用约束的foriegn键。
您可以自动进行级联删除(删除父记录时,将自动删除子记录)。
答案 1 :(得分:2)
您现在添加了MySQL
标记。在这种情况下,这可能会为您完成工作。
DELETE products,
product_ratings
FROM products,
product_ratings
WHERE product_ratings.product_id = products.product_id
AND product_ratings.product_id IN
(SELECT product_id
FROM (SELECT p.product_id
FROM products p
LEFT JOIN product_ratings pr
ON pr.product_id = p.product_id
GROUP BY p.product_id
HAVING COALESCE(AVG(pr.rating), 0) < 3) T)
MySQL does support多表DELETE语法。派生表是为了解决不允许在子查询(it materializes the result into a temporary table)中引用变异(更新或删除目标)表的问题。
答案 2 :(得分:1)
将p.product_id
添加到select语句,并将该查询的结果存储在临时表中。然后使用该临时表在两个单独的删除操作中从product_ratings
和products
中删除。
删除的具体语法取决于您正在使用的RDBMS。
答案 3 :(得分:0)
如果您的DBMS支持它,您可以向ON DELETE CASCADE
表添加带有product_ratings
子句的外键约束,例如:
ALTER TABLE product_ratings ADD CONSTRAINT fk_prodratings_prods
FOREIGN KEY (product_id) REFERENCES products(product_id)
ON DELETE CASCADE;
添加此约束后,您只需要DELETE
表中的products
。上面约束的ON DELETE CASCADE
约束将删除您的评级,例如
DELETE FROM products p
WHERE (SELECT AVG(pr.rating)
FROM product_ratings pr
WHERE pr.product_id = p.product_id) < 3;