我们有一个存储程序,可以对当地报告中的雪况进行平均,然后得出该县的设定百分比。该县被放置在交互式地图上,并应用了颜色深浅。
在只有少数报告的县,即使只有 1 个营业场所,平均值也会设置为 0。这是一个问题,因为颜色表明该县没有开业企业。
我们的解决方案是,如果有一份报告具有“差”、“一般”、“良好”、“优秀”的条件,则将平均值设置为 25;如果有不止一份报告具有这些条件之一,则将平均值设置为 50。
我尝试使用 ANY 运算符实现第一个目标,但我无法实现此目的。我也不知道如何实现第二个目标。
这是当前查询:
ALTER PROCEDURE [dbo].[GetAverageConditionByCounty]
(
@SiteId int = 100
)
AS
BEGIN
SET NOCOUNT ON;
SELECT cg.Name,
AVG(ISNULL(CASE sn.Condition
WHEN 'Poor' THEN 25
WHEN 'Fair' THEN 50
WHEN 'Good' THEN 75
WHEN 'Excellent' THEN 100
ELSE 0 END,-1)) as average
FROM Counties cg
INNER JOIN BaseReports br ON br.CountyId = cg.Id AND br.IsActive = 1
INNER JOIN SnowReport sn ON sn.BaseReportId = br.Id
WHERE br.SiteId = @SiteId
GROUP BY cg.Id, cg.Name
ORDER BY cg.Name
END
以下是原始查询的示例结果:
姓名 | 平均 |
---|---|
A县 | 100 |
B县 | 75 |
C县 | 0 |
D县 | 0 |
E县 | 25 |
为了使用 ANY() 运算符实现第一个目标,这就是我尝试做的:
ALTER PROCEDURE [dbo].[GetAverageConditionByCounty]
(
@SiteId int = 100
)
AS
BEGIN
SET NOCOUNT ON;
SELECT cg.Name,
AVG(ISNULL(CASE sn.Condition
WHEN 'Past Peak' THEN 101
WHEN 'Poor' THEN 25
WHEN 'Fair' THEN 50
WHEN 'Good' THEN 75
WHEN 'Excellent' THEN 100
WHEN sn.Condition = ANY ('Poor', 'Fair', 'Good', 'Excellent' ) THEN 25
ELSE 0 END,-1)) as average
FROM Counties cg
INNER JOIN BaseReports br ON br.CountyId = cg.Id AND br.IsActive = 1
INNER JOIN SnowReport sn ON sn.BaseReportId = br.Id
WHERE br.SiteId = @SiteId
GROUP BY cg.Id, cg.Name
ORDER BY cg.Name
END
尝试 ANY() 时出错:
这是我使用 IN() 运算符的尝试:
ALTER PROCEDURE [dbo].[GetAverageConditionByCounty]
(
@SiteId int = 100
)
AS
BEGIN
SET NOCOUNT ON;
SELECT cg.Name,
AVG(ISNULL(CASE sn.Condition
WHEN 'Past Peak' THEN 101
WHEN 'Poor' THEN 25
WHEN 'Fair' THEN 50
WHEN 'Good' THEN 75
WHEN 'Excellent' THEN 100
WHEN sn.Condition IN ('Poor', 'Fair', 'Good', 'Excellent' ) THEN 25
ELSE 0 END,-1)) as average
FROM Counties cg
INNER JOIN BaseReports br ON br.CountyId = cg.Id AND br.IsActive = 1
INNER JOIN SnowReport sn ON sn.BaseReportId = br.Id
WHERE br.SiteId = @SiteId
GROUP BY cg.Id, cg.Name
ORDER BY cg.Name
END
以下是尝试 IN() 时的错误:
你似乎想要更多这样的东西:
case count(case when sn.Condition in ('Poor', 'Fair', 'Good', 'Excellent') then 1 end)
-- if those are all the possibilities then just use count(*) instead
when 1 then 25
when 2 then 50
else avg(case sn.Condition
when 'Poor' then 25
when 'Fair' then 50
when 'Good' then 75
when 'Excellent' then 100
else 0 end)
end as "average"
它还让您体验两种类型的
case
表达方式。
您还可以利用总是被忽略的空值来保证计算结果不会低于 25。由于对计算的贡献最低的是 25,因此不可能低于该平均值,尽管在没有输入的情况下仍可能计算为 null。 (
else null
也是未明确指定时的默认行为):
coalesce(avg(case sn.Condition
when 'Poor' then 25
when 'Fair' then 50
when 'Good' then 75
when 'Excellent' then 100
else null end), 0) as "average"