这是我删除评论时的触发器,
DELIMITER $$
CREATE TRIGGER after_review_delete
AFTER DELETE ON product_reviews
FOR EACH ROW
BEGIN
UPDATE product
SET
reviews_count = CASE WHEN OLD.status = 1
THEN reviews_count-1
ELSE reviews_count
END,
rating = CASE WHEN OLD.status = 1
THEN CASE
WHEN reviews_count = 0 THEN 0
ELSE (rating*(reviews_count+1)+OLD.rating)/reviews_count
END
ELSE rating
WHERE id = OLD.pid;
END$$
DELIMITER ;
这里是查询的一些解释,它是做什么的,它检查
case
是否审核status = 1
然后这意味着它是一个活跃的审核而不是待定的审核,在它变得活跃之前评级和添加并不重要。
我想问的是该评级或
reviws_count
计算是否准确,因为rating
列值是相关的或reviews_count
以及在计算评级期间我是否会得到reviews_count
初始值或值已更新。
我也可以这样做,但它会再次选择产品,我的应用程序逻辑已经这样做了,感觉有点慢,
DELIMITER $$
CREATE TRIGGER after_review_delete
AFTER DELETE ON product_reviews
FOR EACH ROW
BEGIN
-- Declare local variables to hold current values
DECLARE current_reviews_count INT;
DECLARE current_rating DECIMAL(10, 2);
-- Fetch the current reviews count and rating
SELECT reviews_count, rating INTO current_reviews_count, current_rating
FROM product
WHERE id = OLD.pid;
-- Update the product table with conditional logic
UPDATE product
SET
reviews_count = CASE
WHEN OLD.status = 1 THEN current_reviews_count - 1
ELSE current_reviews_count
END,
rating = CASE
WHEN OLD.status = 1 THEN
CASE
WHEN current_reviews_count - 1 = 0 THEN 0 -- No reviews left
ELSE (current_rating * current_reviews_count - OLD.rating) / (current_reviews_count - 1)
END
ELSE current_rating
END
WHERE id = OLD.pid;
END$$
DELIMITER ;
我想要最准确和最快的解决方案,我的第一种方法是否正确,我可以安全地避免第二种方法吗?
我已经检查了这个答案,但没有要求触发器。
这是我的服务器版本以及操作系统信息。 Mysql 版本 8.0.39-0 ubuntu0.24.04.1 适用于 x86_64 上的 Linux ((Ubuntu))
你的第一种方法似乎是正确的,但是SQL中的操作顺序以及如何使用reviews_count来计算新评级存在问题。
SQL 不保证 UPDATE 语句中表达式的求值顺序。这意味着评级计算中使用的reviews_count值可能不会反映在同一UPDATE操作期间(在减少之后)更新的值。因此,这可能会导致错误的结果。
如果 OLD.status = 1,reviews_count 减 1。 然后,在同一个 UPDATE 语句中,您将使用 Reviews_count 可能仍为原始值来计算新评级。鉴于在评分计算过程中reviews_count可能尚未减少,因此计算可能基于原始reviews_count,从而导致评分不正确。
第二种方法更安全:
由于您在进行计算之前显式获取值,因此您可以确保计算中使用的值是正确且最新的。
此方法避免了 SQL UPDATE 语句中操作顺序的潜在陷阱。
如果你问我,我会建议优化第二种方法。以下是一些简单的步骤;
第二种方法更可靠,可以确保正确计算reviews_count和 rating。尽管它需要额外的 SELECT,但所获得的准确性通常值得权衡。