【问题标题】:Stored procedure for getting sum of entries in table for each ID用于获取每个 ID 表中条目总和的存储过程
【发布时间】:2013-05-07 18:27:54
【问题描述】:

我正在编写一个存储过程,其中我有一个名为 scale 的列,它存储从为每种技能名称选择为 1/ 2/ 3/ 4 的单选按钮的结果。

现在,我想查看特定技能名称 1、技能名称 2、...、技能名称 20 的每个等级 - 1 和 2 以及 3 和 4 下的总人数。

这是我的桌子:

tbl技能:

ID | SkillName  

另一个表为:

tblskillMetrics:

ID | SkillID | EmployeeID | Scale

这是我要写的查询:

Create Procedure spGetSkillMetricsCount
As
Begin
   SELECT 
      tblSkill.Name as skillname,
      (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=1) AS NotAplicable,
      (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=2 ) AS Beginner,
      (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=3 ) AS Proficient,
      (select COUNT(EmployeeID) from tblSkillMetrics where tblSkillMetrics.Scale=4 ) AS Expert
   FROM
      tblSkill
   INNER JOIN 
      tblSkillMetrics ON tblSkillMetrics.SkillID = tblSkill.ID
   GROUP BY 
      tblSkillMetrics.Scale, tblSkill.Name 
   ORDER BY 
      skillname DESC
END

通过使用这个存储过程,我可以获得我想要的结果格式,但在每个的输出中:不适用,初学者,精通或专家是相同的,它是所有条目的总和桌子。

请有人建议我哪里出错了。

【问题讨论】:

    标签: sql stored-procedures join sql-server-2008-r2


    【解决方案1】:

    从逻辑上讲,您按两个标准进行分组,即规模和技能名称。但是,如果我理解正确,每一行都应该代表一个技能名称。因此,您应该只按tblSkill.Name 分组。要在不同的列中获得不同比例的不同计数,您可以使用条件聚合,即(通常)涉及CASE 构造的表达式上的聚合。你可以这样做:

    SELECT 
       tblSkill.Name AS skillname,
       COUNT(CASE tblSkillMetrics.Scale WHEN 1 THEN EmployeeID END) AS NotAplicable,
       COUNT(CASE tblSkillMetrics.Scale WHEN 2 THEN EmployeeID END) AS Beginner,
       COUNT(CASE tblSkillMetrics.Scale WHEN 3 THEN EmployeeID END) AS Proficient,
       COUNT(CASE tblSkillMetrics.Scale WHEN 4 THEN EmployeeID END) AS Expert
    FROM
       tblSkill
    INNER JOIN 
       tblSkillMetrics ON tblSkillMetrics.SkillID = tblSkill.ID
    GROUP BY 
       tblSkill.Name 
    ORDER BY 
       skillname DESC
    ;
    

    请注意,此类查询有一种特殊的语法。它使用PIVOT 关键字,因为您得到的本质上是一个分组结果集,该结果集以分组标准之一为中心,在这种情况下为缩放。这就是 PIVOT 可以达到同样效果的方式:

    SELECT
       skillname,
       [1] AS NotAplicable,
       [2] AS Beginner,
       [3] AS Proficient,
       [4] AS Expert
    FROM (
       SELECT 
          tblSkill.Name AS skillname,
          tblSkillMetrics.Scale,
          EmployeeID
       FROM
          tblSkill
       INNER JOIN 
          tblSkillMetrics ON tblSkillMetrics.SkillID = tblSkill.ID
    ) s
    PIVOT (
       COUNT(EmployeeID) FOR Scale IN ([1], [2], [3], [4])
    ) p
    ;
    

    基本上,PIVOT 意味着分组。源数据集中除一个之外的所有列都是分组标准,即在 PIVOT 子句中未用作聚合函数参数的每一列都是分组标准。其中之一也被指定为以结果为中心的那个。 (同样,在这种情况下,它是规模。)

    因为分组是隐式的,所以使用派生表来避免按不必要的标准进行分组。 Scale 的值成为 PIVOT 子句生成的新列的名称。 (这就是为什么它们在 PIVOT 中列出时用方括号分隔的原因:它们不是该上下文中的 ID,而是标识符 delimited as required by Transact-SQL syntax。)

    【讨论】:

    • 感谢@Andriy M,这很有帮助。我也尝试过类似的方法,但在某处犯了一些错误,因此无法达到结果。感谢您也向我解释了整个事情。
    【解决方案2】:

    一个案例构造而不是所有这些子查询可能会起作用。

    select tblSkill.name skillname
    , case when tblSkillMetrics = 1 then 'Not Applicable'
    etc
    else 'Expert' end level
    , count(employeeid) records
    from tblSkill join tblSkillMetrics 
    on tblSkillMetrics.SkillID = tblSkill.ID
    group by tblSkill.name
    , case when tblSkillMetrics = 1 then 'Not Applicable'
    etc
    else 'Expert' end level
    order by skillname desc
    

    【讨论】:

    • 感谢@Dan Bracuk 的帮助。
    【解决方案3】:

    你可以这样使用:

    SELECT sum(case when tblskillmetrics.scale = 2 then 1 else 0 end) Beginner,  
           sum(case when tblskillmetrics.Scale=3 then 1 else 0 end)Proficient, 
           SUM(case when tblSkillMetrics.Scale=4 then 1 else 0 end)Expert,
           tblSkillGroup.ID AS GroupID,tblSkillGroup.Name AS GroupName,
           tblSkill.ID AS SkillID 
           , tblSkill.Name AS SkillName
    
    FROM  tblSkill INNER JOIN tblSkillMetrics 
             ON tblSkillMetrics.SkillID=tblSkill.ID 
    ORDER BY GroupName DESC 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-31
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-15
      相关资源
      最近更新 更多