在SQL聚合函数中用任意数字替换字母

时间:2018-09-24 09:42:27

标签: sql sql-server case-when

我有一个看起来像这样的表:

+----+-----------+-------+
| id |  subject  | grade |
+----+-----------+-------+
|  1 | english   | 2     |
|  1 | math      | 3     |
|  1 | physics   | 1     |
|  1 | chemistry | 1     |
|  1 | biology   | *     |
|  2 | english   | 1     |
+----+-----------+-------+

我想运行

AVG(grade) OVER (PARTITION BY id ORDER BY id DESC) AS 'Average Grade'

但是,当然,因为*,A,B等等级,所以不起作用。

有没有一种方法可以告诉AVG在其计算中将字母替换为任意值,例如

*。 * = 0

*。 A = 1

*。 B = 2

并忽略N / A或X等字段。

预先感谢

编辑:

我的DBMS是Sql Server

2 个答案:

答案 0 :(得分:3)

您可以尝试在CASE WHEN函数中使用AVG

AVG(CASE WHEN grade = '*' THEN 0 
     WHEN grade = 'A' THEN 1 
     WHEN grade = 'B' THEN 2 
     ....
    ELSE grade END) OVER (PARTITION BY id ORDER BY id DESC) AS 'Average Grade'

注意

我建议您将grade设置为int dataType而不是字符串,因为这样可以更容易计算。

答案 1 :(得分:1)

您可以在case中使用巨型avg()表达式。但是,我建议您有一个引用表或至少一个派生表来处理映射:

第二(partition by id order by id)没有道理。您想要id的完整平均值(我的猜测),还是想要一个连续平均值。所以,

select avg(v.grade_val) over (partition by t.id) as id_average_grade
from t outer apply
     (select 
      from (values ('A', 1), ('B', 2), ('*', 0), ('1', 1), ('2', 2), . . .
           ) v(grade, grade_val)
      where v.grade = t.grade
     ) v(grade_val)

请注意,内部values()可能是善意参考表。