使用删除/存在问题删除记录

时间:2011-02-18 20:31:03

标签: sql mysql

我的问题是我想从两个表中删除记录,删除以下查询结果的记录:

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

表格为productsproduct_ratings,结构如下:

products
--------
product_id [PK] | link | ...

product_ratings
---------------
rating_id [PK] | rating | product_id

感谢任何帮助,以及参考资料的链接,以便更好地了解它是如何完成的。

编辑:抱歉没有说明我正在使用的RDBMS,它是MySQL

EDIT2:现在有点困惑,@ Martin的例子不像其他答案那样使用临时表,我认为这是因为我的模糊问题没有说明我正在使用的RDBMS?

4 个答案:

答案 0 :(得分:2)

您应该在表之间创建一个带有引用约束的foriegn键。

您可以自动进行级联删除(删除父记录时,将自动删除子记录)。

http://en.wikipedia.org/wiki/Foreign_key#CASCADE

答案 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_ratingsproducts中删除。

删除的具体语法取决于您正在使用的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;