1

我读过“如果你在 sql 中使用循环,你可能做错了”,这导致我来到这里。不过,在问题之前,先介绍一下该场景的背景。我有以下数据库结构:

  • “用户”有:
    • UserID int IDENTITY (PK)
    • 可靠性浮动
  • “用户提交”有:
    • 价值浮动
    • 用户 ID 整数 (FK) (PK)
    • 提交 ID (FK) (PK)
    • 时间戳日期时间(PK)
  • “全球提交”有:
    • 理想值浮动
    • 提交 ID (PK)

将 GlobalSubmissions 视为一个表格,其中包含理想情况下用户应提交的理想值。UserSubmissions 是一个包含用户提交的值的表。

我编写了一个函数,通过将用户的“提交”与单个特定的“全局提交”进行比较来估计用户的可靠性:

CREATE FUNCTION dbo.GetUserReliabilityForSubmission(@userID int, @submissionID int)
RETURNS float
AS
BEGIN

    DECLARE @userAverageValue float,
    @idealValue float;

    SET @userAverageValue = (
        SELECT AVG (Value)
            FROM UserSubmissions
        WHERE (UserID = @userID AND SubmissionID = @submissionID));

    SET @idealValue = (
        SELECT IdealValue
        FROM Submission
        WHERE (SubmissionID = @submissionID));

    RETURN 1 - ABS(@userAverageValue - @idealValue);
END

这可行,但它仅根据一个特定的提交 ID 计算用户的可靠性。如果我想计算用户的“全局”可靠性,我需要使用一个循环来遍历用户曾经提交的所有不同的SubmissionID并在其上运行该过程。

在这种情况下使用循环是否有一个很好的选择?

4

1 回答 1

2
SELECT d.UserID, 1 - AVG(ABS(d.avg - d.IdealValue))
FROM (
  SELECT us.UserID, gs.SubmissionID, gs.IdealValue, AVG(us.Value) as avg FROM UsersSubmissions us
  JOIN GlobalSubmissions gs ON gs.SubmissionID = us.SubmissionID
  GROUP BY us.UserID, gs.SubmissionID, gs.IdealValue) d
GROUP BY d.UserId

工作示例:http ://sqlfiddle.com/#!6/8d880/8

但是,我会说这不是定义可靠性的好方法。我认为您应该考虑将其更改为以下内容:

SELECT d.UserID, 1 - AVG(ABS(d.avg - d.IdealValue) / ABS(d.IdealValue))
FROM (
  SELECT us.UserID, gs.SubmissionID, gs.IdealValue, AVG(us.Value) as avg FROM UsersSubmissions us
  JOIN GlobalSubmissions gs ON gs.SubmissionID = us.SubmissionID
  GROUP BY us.UserID, gs.SubmissionID, gs.IdealValue) d
GROUP BY d.UserId

还有例子:http ://sqlfiddle.com/#!6/8d880/14

变化是什么?它把错误相对于价值本身。当它实际上是6时说x = 5和当它是501时说x = 500是有区别的。

于 2013-03-16T11:24:04.837 回答