存储过程返回不正确的值

时间:2014-10-24 05:37:22

标签: sql-server stored-procedures

我想用下面存储的proc来计算出勤率,但它返回的值不正确。任何人都可以帮助我发现我的sp plz中的错误。

CREATE PROCEDURE [dbo].[percentage]
@stdid int,
@strtdate date,
@enddate date
AS
BEGIN
Select [std_status], 
((select Count(std_status) where (std_status='P')) * 100 / 
(Select Count(*) From [DB].[dbo].[attendance] where admission_Id_int=@stdid and    
(entry_date BETWEEN @strtdate and @enddate))) 
as attendencepercentage
From [DB].[dbo].[attendance]
where std_status='P' and admission_Id_int=@stdid
Group By std_status
END

2 个答案:

答案 0 :(得分:0)

我无法理解您的查询。所以让我们从这个开始吧。

下面我有很多条款。您需要确定哪些是您的百分比的分子和分母。我无法从你的查询中解决这个问题。

select
sum(case when std_status='P' THEN 1 ELSE 0 END) as Term1,
sum(case when admission_Id_int=@stdid THEN 1 ELSE 0 END) as Term2,
sum(case when std_status='P' and admission_Id_int=@stdid THEN 1 ELSE 0 END) as Term3,
sum(case when std_status='P' THEN 1 ELSE 0 END) / 
sum(case when admission_Id_int=@stdid THEN 1 ELSE 0 END) as SampleDivisionOfTerm1AndTerm2
From [DB].[dbo].[attendance]
where entry_date BETWEEN @strtdate and @enddate
Group By std_status

答案 1 :(得分:0)

您的查询返回错误百分比的原因是因为'P'行的数量不包括entry_date上的过滤器,而其他计数则包含@strtdate。这意味着,对于@enddateentry_date指定的相当小的范围,第一个计数可能超过第二个计数,因此除法的结果可能会大于100%。

所以,也许这个问题的一个简单解决方案就是在主WHERE子句中重复Select [std_status], ((select Count(std_status) where (std_status='P')) * 100 / (Select Count(*) From [DB].[dbo].[attendance] where admission_Id_int=@stdid and (entry_date BETWEEN @strtdate and @enddate))) as attendencepercentage From [DB].[dbo].[attendance] where std_status='P' and admission_Id_int=@stdid and (entry_date BETWEEN @strtdate and @enddate) Group By std_status 过滤器:

(select Count(std_status) where (std_status='P'))

然而,正如所写,这样的查询将是不必要的复杂。例如,此子查询

COUNT(*)

完全是多余的,可以简单地重写

std_status='P'

因为主WHERE子句已经有SELECT std_status = 'P', AttendancePercentage = COUNT(CASE std_status WHEN 'P' THEN 1 END) * 100 / COUNT(*) FROM [DB].[dbo].[attendance] WHERE admission_Id_int = @stdid AND entry_date BETWEEN @strtdate and @enddate ;过滤器。但实际上,您可以以避免任何子查询的方式重写整个查询。这是一个例子:

std_status

上述查询检索与指定参数匹配的所有行,而不考虑COUNT(*),分别计算所有行('P')和匹配COUNT(CASE std_status WHEN 'P' THEN 1 END)状态(AttendancePercentage)的行并使用结果来计算GROUP BY std_status

还要注意重写中没有std_status。在那里不需要它,因为其中一个计数完全忽略std_status而另一个计数使用不同的列。

我不确定您是否确实需要输出中的{{1}}列,但是如果您这样做并且必须显示计算百分比的状态,我将其添加为带有硬编码的计算列值。否则,该列似乎是多余的,可以轻松删除。