我在PHP中有一个SQL查询,当用户取消投票时重新计算平均评分:
$delete_vote = $conn->prepare("UPDATE table SET
votes = votes - 1,
total_value = total_value - :recall_vote,
average = (total_value * 10) / (total_votes * 10)
WHERE id=id");
问题在于重新计算平均投票率。即使我为列' total_value'设置了默认值而对于平均而言为零,如果有问题的查询只有一个投票,并且正在调用该投票,则平均值将被设置为null而不是0,正如我希望的那样。解决这个问题的一种可能方法是从数据库中检索这两个值,检查它们是否为空,然后将它们更改为0 - 但这有点麻烦。相反,我想知道是否有更简单的解决方案。
我尝试过的另一件事是在计算中加零,希望null转换为0:
$vote_count = $conn->prepare("UPDATE table SET
total_votes = (0 + total_votes) + 1
这也不起作用。有一个简单的解决方案吗?
答案 0 :(得分:1)
由于您使用的是PHP,我假设您正在使用MySQL。但我认为每个RDBMS都有类似的功能......在MySQL中,您可以定义值为NULL
时的回退值。如果值不是NULL
,则会返回原始值:
IFNULL(something, 0)
除此之外,可能会稍微偏离主题; 我通常会尝试通过保存平均值来避免非规范化 - 在大多数情况下,可以在查询数据库时进行计算。但这取决于具体情况。
答案 1 :(得分:1)
我完全不明白你的where
条款 - 几乎总是评价为真。
要使用的正确语法是几乎所有数据库中都可用的ANSI标准COALESCE()
或CASE
。你可以写成:
UPDATE table
SET votes = votes - 1,
total_value = total_value - :recall_vote,
average = COALESCE((total_value * 10) / NULLIF(total_votes * 10, 0), 0)
WHERE id = $id -- something other than `id`
我想我会倾向于明确:
UPDATE table
SET votes = votes - 1,
total_value = total_value - :recall_vote,
average = (CASE WHEN total_votes > 0
THEN total_value / total_votes
ELSE 0
END)
WHERE id = $id -- something other than `id`
顺便说一句,为什么你在分子和分母中乘以10?似乎没必要。