【问题标题】:Why is my stored procedure returning 0?为什么我的存储过程返回 0?
【发布时间】:2016-06-19 18:32:06
【问题描述】:

我试图得到pointsEarned 列的总和和pointsPossible 列的总和。我想把它变成一个百分比。我的问题是我的 SP 总是返回 0,即使有给定 enrollmentId 的行具有前一列的值。

我做错了什么?

ALTER PROCEDURE GetPercentage 
    @enrollmentId int
AS
BEGIN
    DECLARE @pointsEarned int;
    DECLARE @pointsPossible int;

    SET NOCOUNT ON;

    SELECT 
        @pointsEarned = CAST(SUM(pointsEarned) OVER() AS decimal), 
        @pointsPossible = CAST(SUM(pointsPossible) OVER() AS decimal)
    FROM 
        Assignments
    WHERE 
        enrollmentId = @enrollmentId

    RETURN @pointsEarned / @pointsPossible
END
GO

这是数据库表:

我执行了存储过程并传入了69的enrollmentId,它仍然返回0。

【问题讨论】:

  • 我会去掉 RETURN 并用 SELECT 替换它
  • 显示你的 exec 脚本
  • 你为什么要去掉退货并用select代替?并没有解决问题,完全改变了SP的使用方式。
  • 您希望在您的示例中得到什么结果?

标签: sql-server tsql stored-procedures


【解决方案1】:
  1. 使用简单的SUM 而不使用OVER

  2. RETURN 只能返回 int。如果您的百分比小于 100%,整数除法将始终返回 0,因此乘以 100 将返回整数百分比而不是比率。

  3. 检查你没有被零除。

程序

ALTER PROCEDURE GetPercentage 
    @enrollmentId int
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @pointsEarned int;
    DECLARE @pointsPossible int;

    SELECT 
        @pointsEarned = SUM(pointsEarned),
        @pointsPossible = SUM(pointsPossible)
    FROM 
        Assignments
    WHERE 
        enrollmentId = @enrollmentId
    ;

    RETURN 
        CASE WHEN @pointsPossible <> 0
        THEN 100 * @pointsEarned / @pointsPossible
        ELSE 0 END;

END
GO

【讨论】:

  • @MitchWheat,我想我知道SUM() OVER() 做了什么。如果我正确理解了这个问题,OP 需要一个简单的总和(一行中的一个数字),而不是多行中的总和。
  • 你的意思是喜欢我发布的答案?但是关于 RETURN 的好处只能返回一个 int。
  • @MitchWheat,是的,你的答案和我的非常相似。您决定将SELECT 的结果作为结果集,它可以保存非整数值(decimalfloat)。我留下了 RETURNs 整数值的原始方法。顺便说一句,不需要GROUP BY,因为WHERE 中有过滤器。
  • RE: GROUP BY":是的,我知道。这是出于习惯。
【解决方案2】:

分母 (pointsPossible) 大于分子 (pointsEarned) 的整数除法返回零。

写作(修订):

ALTER PROCEDURE GetPercentage 
    @enrollmentId int
AS
BEGIN
    SET NOCOUNT ON;

    SELECT 
        Percent = case when sum(pointsPossible) > 0 then (1.0 * sum(pointsEarned)) / sum(pointsPossible) else 0 end
    FROM 
        Assignments
    WHERE 
        enrollmentId = @enrollmentId
    GROUP BY
        enrollmentId 
END
GO

正如@ Nick.McDermaid 所指出的,由于此过程返回一个标量值,因此将其定义为函数而不是存储过程可能更合适。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-18
    • 2018-08-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 2013-01-26
    • 2021-10-24
    相关资源
    最近更新 更多