SQL select语句求和几种情况的总和并返回百分比?

时间:2019-02-28 01:03:39

标签: c# sql asp.net sql-server

我有一个用于员工评估记录的表,该表与包含评估主题的另一个表相关,它具有3种类型的评估,例如:

  1. 正负(分别在表“ -3,-2”中表示为整数值)。
  2. 否和是(分别在表“ -1,0”中表示为整数值)。
  3. 从1到5的值(表示为具有相同值的整数)。

这是表格设计的示例:

--------------------
| evaID      | int |
--------------------
| employeeID | int |
--------------------
| evaRec     | int |
--------------------

这是表数据的示例:

-------------------------------
| evaID | employeeID | evaRec |
-------------------------------
| 1     | 00001      | -3     |
-------------------------------
| 17    | 00001      | -2     |
-------------------------------
| 19    | 00001      | -2     |
-------------------------------
| 19    | 00001      | -1     |
-------------------------------
| 16    | 00002      | 3      |
-------------------------------
| 16    | 00005      | 0      |
-------------------------------

现在我想要的是根据类型来选择特定员工的所有记录的总和,作为评估的百分比,但是要像前那样将这三种类型分开(与该表数据无关)

  • 正负类型:20%/ 80%
  • 否&是:30%/ 70%
  • 1、2、3、4或5类型:10%/ 50%/ 5%/ 15%/ 20%

所以基本上我希望select语句返回6个float值,这些值代表所有上述类型的百分比(floatNegative,floatNo,float1,float2,float3和float4),如果可能的话-,但我知道这很困难,因为我还无法弄清楚其背后的逻辑-我希望它返回第7个浮点值,代表对良好或不良评估的所有百分比,但我仍无法弄清楚如何混合使用“是或否”是2个因子的百分比,“ 1,2,3,4或5”是5个因子的百分比!

因此,稍后在我的C#代码中,我将使用以下选择结果:

  • floatNegative = 20(负数= 20%,正数= 100-floatNegative = 80%)
  • floattNo = 30(否= 30%,是= 100-floatNo = 70%)
  • 以此类推,还有其他5个数字...

这意味着根据上述评估类型,我有3个单独的百分比计算组。

所以最后,如果我对上表中的员工“ 00001”运行查询,则会得到结果:

  • floatNegative = 33.3
  • floatPositive = 66.6
  • floatNo = 100.0

因为他有1 x “负”记录(-3)和2 x “正”记录(-2),总共3条记录。 (“否定/肯定”类型评估组上的),并且他有1 x “否”记录(-1),但没有任何”是”记录(0),这就是为什么“否”(评估的“否/是”类型组中的 )的结果是100%的原因。而且我不在乎其他类型的结果(如果他没有任何记录,例如1,2,3,4,5),它可能是负浮点值,所以我可以在我的C#代码上区分它以找出他还没有这种类型的记录,并且在我的asp.net最终标记中隐藏了百分比指标文本。

1 个答案:

答案 0 :(得分:1)

我认为您正在寻找条件聚合。逻辑是GROUP BY employeeID,然后使用各种SUM(CASE ...)表达式来计算中间和。

假设您要对雇员的评价为阴性

SUM(CASE WHEN evaRec = -2 THEN 1 ELSE 0 END)

您还可以计算总的正反馈和负反馈:

SUM(CASE WHEN evaRec IN (-2, -3) THEN 1 ELSE 0 END)

这里是使用该原理的完整查询。对于二进制评估类型(正/负,是/否),仅计算两个值之一(另一个仅为1 - <this_value>)。对于1/2/3/4/5类型,每个比例都是单独计算的。

SELECT
    employeeID,
    1.0 * SUM(CASE WHEN evaRec = -2 THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN evaRec IN (-2, -3) THEN 1 ELSE 0 END), 0) PercentPositive,
    1.0 * SUM(CASE WHEN evaRec =  0 THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN evaRec IN (-1, 0)  THEN 1 ELSE 0 END), 0) PercentYes,
    1.0 * SUM(CASE WHEN evaRec =  1 THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN evaRec IN (1, 2, 3, 4, 5)  THEN 1 ELSE 0 END), 0) PercentValue1,
    1.0 * SUM(CASE WHEN evaRec =  2 THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN evaRec IN (1, 2, 3, 4, 5)  THEN 1 ELSE 0 END), 0) PercentValue2,
    1.0 * SUM(CASE WHEN evaRec =  3 THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN evaRec IN (1, 2, 3, 4, 5)  THEN 1 ELSE 0 END), 0) PercentValue3,
    1.0 * SUM(CASE WHEN evaRec =  4 THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN evaRec IN (1, 2, 3, 4, 5)  THEN 1 ELSE 0 END), 0) PercentValue4,
    1.0 * SUM(CASE WHEN evaRec =  5 THEN 1 ELSE 0 END) / NULLIF(SUM(CASE WHEN evaRec IN (1, 2, 3, 4, 5)  THEN 1 ELSE 0 END), 0) PercentValue5
FROM t
GROUP BY employeeID

NB:需要特别注意避免被0除。

DB Fiddle 及其示例数据将返回:

employeeID | PercentPositive | PercentYes     | PercentValue1  | PercentValue2  | PercentValue3  | PercentValue4  | PercentValue5 
---------: | :-------------- | :------------- | :------------- | :------------- | :------------- | :------------- | :-------------
         1 | 0.666666666666  | 0.000000000000 | null           | null           | null           | null           | null          
         2 | null            | null           | 0.000000000000 | 0.000000000000 | 1.000000000000 | 0.000000000000 | 0.000000000000
         5 | null            | 1.000000000000 | null           | null           | null           | null           | null