选择排名依据的前5名,并按多列

时间:2017-06-23 18:20:44

标签: sql sql-server

我已经搜索了这样做的方法,但我不确定如何在我的特定场景中应用建议,而且我也不知道哪种方法是考虑到数据上下文的最佳或最准确的方法。 / p>

我正在寻找从包含员工分数的表格中选择最佳表现者的最佳方式,针对特定测试多次给出相同的测量值。因此,随着时间的推移,员工可能会使用相同的测试/测量进行多次评估,并且我试图选择给定时期内的最佳表现者。在此示例中,度量记录在Question1和Question2列中,员工在EmployeeID列中指定。分数的比例因列而异,并且通过测试,但都是最小的0或1.在样本数据中,测试1000有列Question1(0-10)和Question2(1-7),但是你不要根据数据确定无误的比例,你只知道每列的最小值为0或1,并且可以为空,这意味着该值应从平均计算中排除。我希望能够说,给我测试1000的两个最佳表现者并根据该表现对它们进行相应的订购。

   ID            TestID        Question1       Question2       Question3       EmployeeID
   1              1000             10             null            null             12
   2              1000             10              7              null             12
   3              1000             10              7              null             12
   4              1000             10              7              null             12
   5              1000             10              7              null             12
   6              1000             10              7              null             5
   7              1000             10              7              null             5
   8              1000             10              7              null             5
   9              1000             10              7              null             5
   10             1000             10              7              null             5
   11             1000             10              7              null             5
   12             1000             10              7              null             5
   13             1000             10              7              null             5
   14             1000             10             null            null             5
   15             1000             10              7              null             5
   16             2000             5               10              10              3
   17             2000             5               0               3               3
   18             2000            null             9               8               6
   19             2000             5               10              9               6
   20             2000            null             10              9               7
   21             2000            null             10              9               7

在这个例子中,对于测试1000,如果我得到排名前两位的表现者,结果应该是员工5和员工12排名相同,因为虽然他们都有10和7并且每个都包含一个null,这应该是不予考虑。

这个SQL是向我建议的,但似乎并不像我想要的那样工作。由此产生的SumAve对于员工5最终为8.5789,对于员工12最终为8.6667,这似乎不正确,因为他们的记录得分具有相同的平均值,并且他们不应因为有任何空值而受到处罚。但即使他们是这样,这与我认为的情况正好相反,因为员工5有更多的记录(7s),我认为他们的平均值会受到缺失/低分的影响。

SELECT TOP 2
  EmployeeID
 ,NoOfResults
 ,Question1
 ,Question2
 ,Question3
 ,SumAve
FROM (SELECT
    [EmployeeID]
   ,COUNT(*) AS NoOfResults
   ,AVG([Question1]) AS Question1
   ,AVG([Question2]) AS Question2
   ,AVG([Question3]) AS Question3
   ,SUM(ISNULL([Question1], 0) + ISNULL([Question2], 0) + ISNULL([Question3], 0)) / 
    SUM(
    CASE
      WHEN Question1 IS NULL THEN 0
      ELSE 1
    END +
    CASE
      WHEN Question2 IS NULL THEN 0
      ELSE 1
    END +
    CASE
      WHEN Question3 IS NULL THEN 0
      ELSE 1
    END) AS SumAve
  FROM Table1
  WHERE TestID = '1000'
  GROUP BY [EmployeeID] perform
ORDER BY SumAve DESC, EmployeeID ASC

另外,最后一个扳手,记录可能包含Question1,Question2和Question3的所有空值。意味着给出了测试,但没有记录得分(无论出于何种原因)。在这种情况下,同样应该忽略空值,如果这是他们唯一的记录,但是如果它们存在则使用其他记录,那么雇员没有等级或最低等级/不被包括在内。  而且我认为一个员工可能有多个记录但在所有记录的一列中都是空的,所以我也添加了这些记录。让我知道,如果这是打破骆驼背部的稻草,因为如果是这样的话,我可能能够在现有数据中改变一些东西。

感谢您的关注,非常感谢您的帮助。

更新 -

使用@scsimon建议的方法似乎并没有给我我想要的东西。似乎结果受到空值的影响,我之前提到的不应该用来惩罚员工的总体得分/排名。在以下示例中,员工10和5都具有最高分(10和7),但员工5缺少一个分数,这不应影响他们的排名。员工12的得分并不完美(一个得分为9而不是10),这应该反映的排名低于员工10和5,但正如您所看到的那样,员工5最终会降低,因此他们因缺失而受到处罚得分,他们不应该。测试1000的排名应该是员工10,5,11和13位于顶部,员工12位于其下方。

SQL for data

DECLARE @table TABLE (
  ID INT IDENTITY(1,1) NOT NULL
 ,TestID INT
 ,Question1 INT
 ,Question2 INT
 ,Question3 INT
 ,EmployeeID INT
)
INSERT INTO @table
  VALUES 
  (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, NULL, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 12),
  (1000, 9, 7, NULL, 12),
  (1000, 10, 7, NULL, 12),
  (1000, 10, 7, NULL, 12),
  (1000, 10, 7, NULL, 12),
  (1001, 10, 7, NULL, 12),
  (1001, NULL, 6, NULL, 12),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, NULL, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 13),
  (1000, 10, 7, NULL, 13)

数据

     ID       TestID   Question1  Question2  Question3  EmployeeID
     18        1000        10         7         null        5     
     19        1000        10         7         null        5     
     20        1000        10         7         null        5     
     21        1000        10         7         null        5     
     22        1000        10         7         null        5     
     23        1000        10         7         null        5     
     24        1000        10         7         null        5     
     25        1000        10         7         null        5     
     26        1000        10        null       null        5     
     27        1000        10         7         null        5     
     1         1000        10         7         null        10    
     2         1000        10         7         null        10    
     3         1000        10         7         null        10    
     4         1000        10         7         null        10    
     5         1000        10         7         null        10    
     6         1000        10        null       null        11    
     7         1000        10         7         null        11    
     8         1000        10         7         null        11    
     9         1000        10         7         null        11    
     10        1000        10         7         null        11    
     11        1000        10         7         null        12    
     12        1000        9          7         null        12    
     13        1000        10         7         null        12    
     14        1000        10         7         null        12    
     15        1000        10         7         null        12    
     16        1001        10         7         null        12    
     17        1001       null        6         null        12    
     28        1000        10         7         null        13    
     29        1000        10         7         null        13    

建议1:结果的SQL

SELECT
  t.EmployeeID
 ,t.TestID
 ,SUM(ISNULL(Question1, 0) + ISNULL(Question2, 0) + ISNULL(Question3, 0)) / (COUNT(t.TestID) * 1.00) AS Ranking
FROM @table t
GROUP BY t.EmployeeID
        ,t.TestID
ORDER BY t.TestID,
Ranking DESC

建议1:结果

   EmployeeID        TestID          Ranking    
       10             1000            17.0      
       13             1000            17.0      
       12             1000            16.8      
        5             1000            16.3      
       11             1000            15.6      
       12             1001            11.5      

关于另一个建议,它似乎没有输出我需要的东西 -

建议2:结果的SQL

SELECT
  EmployeeID
 ,TestID
 ,SUM(ISNULL(Q1, 0) + ISNULL(Q2, 0) + ISNULL(Q3, 0)) / MIN(CASE
    WHEN Q1 IS NULL THEN 0.0
    ELSE 1.0
  END +
  CASE
    WHEN Q2 IS NULL THEN 0.0
    ELSE 1.0
  END +
  CASE
    WHEN Q3 IS NULL THEN 0.0
    ELSE 1.0
  END) AS AverageScore
FROM cte
GROUP BY EmployeeID
        ,TestID
ORDER BY TestID
, AverageScore  

建议2:结果

   EmployeeID        TestID       AverageScore  
        5             1000             8.5      
       10             1000             8.5      
       11             1000             8.5      
       12             1000             8.5      
       13             1000             8.5      
       12             1001             8.5      

2 个答案:

答案 0 :(得分:1)

由于员工不应该因为没有回答问题而停靠,我认为应该这样做。

select 
    t.EmployeeID,
    t.TestID,
    Sum(isnull(Question1,0) + isnull(Question2,0) + isnull(Question3,0)) / (count(t.TestID) * 1.00)
from 
    @table t
group by
    t.EmployeeID,
    t.TestID
order by
    t.TestID

或者,如果我在上面的假设中不正确,那么这个查询更像你想要的,这是基于他们个人尝试的每个employeeid的平均值。

function lcm(arr) {
  arr = arr.sort(function(a, b) {
    return a - b;
  });
  var j = 1;
  var num = arr[0];
  for (i = 1; i < arr.length; i++) {
    while (num % arr[i] !== 0) {
      j = j + 1;
      num = j * arr[0];
    }
    arr[0] = num;
  }
  return num;
}

console.log(lcm([3, 5, 6, 10]));

答案 1 :(得分:0)

我找到了解决方案。希望其他人可以从中受益。原来这是一个简单的调整。基本上我得到每个问题的员工平均分数,并将它们加在一起创建一个索引,以便我可以对它们进行排名。我已经尝试了多个真实的数据场景,它似乎是一种测量和排序每个场景的准确方法。以下是一些示例数据,演示了一些场景。此外,在我的示例中,我将两个测试中的排名结合起来(在这种情况下,它们将是基本相同的测试,但是不同的修订)。

DECLARE @table1 TABLE (
  ID INT IDENTITY (1, 1) NOT NULL
 ,TestID INT
 ,Question1 FLOAT
 ,Question2 FLOAT
 ,Question3 FLOAT
 ,EmployeeID INT
)
DECLARE @table2 TABLE (
  EmployeeID INT
 ,Description VARCHAR(50)
)

INSERT INTO @table1
  VALUES (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, 7, NULL, 10),
  (1000, 10, NULL, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 11),
  (1000, 10, 7, NULL, 12),
  (1000, 9, 7, NULL, 12),
  (1000, 10, 7, NULL, 12),
  (1000, 10, 7, NULL, 12),
  (1000, 10, 7, NULL, 12),
  (1001, 10, 7, NULL, 12),
  (1001, NULL, 6, NULL, 12),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, NULL, NULL, 5),
  (1000, 10, 7, NULL, 5),
  (1000, 10, 7, NULL, 13),
  (1000, 10, 7, NULL, 13),
  (1000, NULL, NULL, NULL, 14)
INSERT INTO @table2
  VALUES (10, 'peter (10s & 7s)')
  ,(11, 'michael (10s & 7s, x7)')
  ,(12, 'samir (mixed)')
  ,(13, 'milton (10s & 7s, <count)')
  ,(5, 'tom (10s & 7s, x7)')
  ,(14, 'bob (nulls)')

SELECT
  t1.TestID
 ,t1.EmployeeID
 ,t1.Question1
 ,t1.Question2
 ,t1.Question3
FROM @table1 t1
INNER JOIN @table2 t2
  ON t1.EmployeeID = t2.EmployeeID
ORDER BY t1.EmployeeID, TestID

SELECT
  t1.EmployeeID
 ,t2.Description
 ,AVG(t1.Question1) AS Question1
 ,AVG(t1.Question2) AS Question2
 ,AVG(t1.Question3) AS Question3
 ,COUNT(t1.EmployeeID) AS NoOfTests
 ,ISNULL(AVG(t1.Question1), 0) + ISNULL(AVG(t1.Question2), 0) + ISNULL(AVG(t1.Question3), 0) AS Rank
FROM @table1 t1
INNER JOIN @table2 t2
  ON t1.EmployeeID = t2.EmployeeID
WHERE t1.TestID = 1000
OR t1.TestID = 1001
GROUP BY t1.EmployeeID
        ,t2.Description
ORDER BY rank DESC, NoOfTests DESC

测试数据:

TestID   EmployeeID Question1  Question2  Question3 
 1000        5         10.0       7.0        null   
 1000        5         10.0       7.0        null   
 1000        5         10.0       7.0        null   
 1000        5         10.0       7.0        null   
 1000        5         10.0       7.0        null   
 1000        5         10.0       7.0        null   
 1000        5         10.0       7.0        null   
 1000        5         10.0       7.0        null   
 1000        5         10.0       null       null   
 1000        5         10.0       7.0        null   
 1000        10        10.0       7.0        null   
 1000        10        10.0       7.0        null   
 1000        10        10.0       7.0        null   
 1000        10        10.0       7.0        null   
 1000        10        10.0       7.0        null   
 1000        11        10.0       null       null   
 1000        11        10.0       7.0        null   
 1000        11        10.0       7.0        null   
 1000        11        10.0       7.0        null   
 1000        11        10.0       7.0        null   
 1000        12        10.0       7.0        null   
 1000        12        9.0        7.0        null   
 1000        12        10.0       7.0        null   
 1000        12        10.0       7.0        null   
 1000        12        10.0       7.0        null   
 1001        12        10.0       7.0        null   
 1001        12        null       6.0        null   
 1000        13        10.0       7.0        null   
 1000        13        10.0       7.0        null   
 1000        14        null       null       null   

结果数据:

EmployeeID         Description        Question1  Question2  Question3  NoOfTests  Rank           
     5         tom (10s & 7s, x7)       10.0        7.0       null        10      17.0           
    10          peter (10s & 7s)        10.0        7.0       null         5      17.0           
    11       michael (10s & 7s, x7)     10.0        7.0       null         5      17.0           
    13      milton (10s & 7s, <count)   10.0        7.0       null         2      17.0           
    12            samir (mixed)         9.833      6.857      null         7      16.69          
    14             bob (nulls)          null        null      null         1       0.0