如何使用 SQL 聚合一些概念类的值?

Posted

技术标签:

【中文标题】如何使用 SQL 聚合一些概念类的值?【英文标题】:How do I aggregate values respect to some conceptual classes with SQL? 【发布时间】:2016-10-10 01:48:11 【问题描述】:

我要解决的问题是一些值的分类,以便通过 SQL 提取一些知识。

将要提出的sql方案可以应用于由少数类组成的分类系统

我们将考虑一个简单的案例,通过分层排序进行聚合。特别是我们的分类 系统将由几个班级组成,每个班级对应一定天数的班级 小于不同数量。

类的数量应该非常有限。

例如:所有天数小于 7 的班级,所有天数小于 6 的班级, 由所有天数少于五天组成的班级,以此类推……

我受到堆栈溢出问题的启发..Aggregation of Data

我们要使用的sql是mysql dbms上实现的版本。 对于答案中报告的示例,您可以使用 SQL Fiddle:http://sqlfiddle.com

【问题讨论】:

【参考方案1】:

基于 SQL 中的分类系统的值聚合

要处理此类问题,在我们问题中定义的约束条件下,我们可以开始考虑我们的 由一些表记录组成的分类系统,代表我们将考虑的类 执行我们的计算,我们的参考系统。

我们的目标是根据我们的类计算一些值,对于每个类我们想知道某事的百分比..

那么,让我们创建我们的类表..

表“类”的问题。

 Class         Reference_Score 
----------------------------
   1              1800      
   3              1800      
   5              1800      
   7              1800      

此表的每条记录代表所有值小于字段“Class”的值的类:

..然后是我们的“分数”

some_order   order_score
--------------------------
   1           90
   3           80
   4          560
   6          980
   7         1050   

好的..我们想知道每个班级的百分比分数,即所有分数总和的关系 属于具有分配给该类的分数的类,我们的参考分数:

percentage_score = ( SUM(order_score)/Reference_Score ) * 100 

ok,开始吧..(后面的sql是MySql Dbms的实现)

1.第一件事是按顺序为我们分数的每个值分配标志:

    select
    Scores.some_order, Scores.order_score,
    case when Scores.some_order <= 7 then '1_7' else '' end seven,
    case when Scores.some_order <= 6 then '1_6' else '' end six,
    case when Scores.some_order <= 5 then '1_5' else '' end five,
    case when Scores.some_order <= 4 then '1_4' else '' end four,
    case when Scores.some_order <= 3 then '1_3' else '' end three,
    case when Scores.some_order <= 2 then '1_2' else '' end two,
    case when Scores.some_order <= 1 then '1_1' else '' end one
    FROM Scores


this is the result:

    | some_order | order_score | seven | six | five | four | three | two | one |
    |------------|-------------|-------|-----|------|------|-------|-----|-----|
    |          1 |          90 |   1_7 | 1_6 |  1_5 |  1_4 |   1_3 | 1_2 | 1_1 |
    |          3 |          80 |   1_7 | 1_6 |  1_5 |  1_4 |   1_3 |     |     |
    |          4 |         560 |   1_7 | 1_6 |  1_5 |  1_4 |       |     |     |
    |          6 |         980 |   1_7 | 1_6 |      |      |       |     |     |
    |          7 |        1050 |   1_7 |     |      |      |       |     |     |
    ----------------------------------------------------------------------------            

2.现在,我们可以开始计算每个分数的总和,并将这个总和放在计算字段中,每个计算字段代表我们问题的一个类别,我们将得到的表格记录,代表同质类别的分数

select
case when Scores_Flagged.seven = '1_7' then sum(Scores_Flagged.order_score) else 0 end tot_seven,
case when Scores_Flagged.six   = '1_6' then sum(Scores_Flagged.order_score) else 0 end tot_six,
case when Scores_Flagged.five  = '1_5' then sum(Scores_Flagged.order_score) else 0 end tot_five,
case when Scores_Flagged.four  = '1_4' then sum(Scores_Flagged.order_score) else 0 end tot_four,
case when Scores_Flagged.three = '1_3' then sum(Scores_Flagged.order_score) else 0 end tot_three,
case when Scores_Flagged.two   = '1_2' then sum(Scores_Flagged.order_score) else 0 end tot_two,
case when Scores_Flagged.one   = '1_1' then sum(Scores_Flagged.order_score) else 0 end tot_one
from
(
  select
  Scores.some_order, Scores.order_score,
  case when Scores.some_order <= 7 then '1_7' else '' end seven,
  case when Scores.some_order <= 6 then '1_6' else '' end six,
  case when Scores.some_order <= 5 then '1_5' else '' end five,
  case when Scores.some_order <= 4 then '1_4' else '' end four,
  case when Scores.some_order <= 3 then '1_3' else '' end three,
  case when Scores.some_order <= 2 then '1_2' else '' end two,
  case when Scores.some_order <= 1 then '1_1' else '' end one
  FROM Scores
) Scores_Flagged
group by seven, six, five, four, three, two, one

    | tot_seven | tot_six | tot_five | tot_four | tot_three | tot_two | tot_one |
    |-----------|---------|----------|----------|-----------|---------|---------|
    |      1050 |       0 |        0 |        0 |         0 |       0 |       0 |
    |       980 |     980 |        0 |        0 |         0 |       0 |       0 |
    |       560 |     560 |      560 |      560 |         0 |       0 |       0 |
    |        80 |      80 |       80 |       80 |        80 |       0 |       0 |
    |        90 |      90 |       90 |       90 |        90 |      90 |      90 |
    -----------------------------------------------------------------------------

3.此时,让我们获取同质类的总分,它们将成为我们计算的基础

select 
    sum(Scores_by_Omogeneous_Classes.tot_seven) tot_seven,
    sum(Scores_by_Omogeneous_Classes.tot_six) tot_six,
    sum(Scores_by_Omogeneous_Classes.tot_five) tot_five,
    sum(Scores_by_Omogeneous_Classes.tot_four) tot_four,
    sum(Scores_by_Omogeneous_Classes.tot_three) tot_three,
    sum(Scores_by_Omogeneous_Classes.tot_two) tot_two,
    sum(Scores_by_Omogeneous_Classes.tot_one) tot_one
    from
    (
      select
      case when Scores_Flagged.seven = '1_7' then sum(Scores_Flagged.order_score) else 0 end tot_seven,
      case when Scores_Flagged.six   = '1_6' then sum(Scores_Flagged.order_score) else 0 end tot_six,
      case when Scores_Flagged.five  = '1_5' then sum(Scores_Flagged.order_score) else 0 end tot_five,
      case when Scores_Flagged.four  = '1_4' then sum(Scores_Flagged.order_score) else 0 end tot_four,
      case when Scores_Flagged.three = '1_3' then sum(Scores_Flagged.order_score) else 0 end tot_three,
      case when Scores_Flagged.two   = '1_2' then sum(Scores_Flagged.order_score) else 0 end tot_two,
      case when Scores_Flagged.one   = '1_1' then sum(Scores_Flagged.order_score) else 0 end tot_one
      from
      (
        select
        Scores.some_order, Scores.order_score,
        case when Scores.some_order <= 7 then '1_7' else '' end seven,
        case when Scores.some_order <= 6 then '1_6' else '' end six,
        case when Scores.some_order <= 5 then '1_5' else '' end five,
        case when Scores.some_order <= 4 then '1_4' else '' end four,
        case when Scores.some_order <= 3 then '1_3' else '' end three,
        case when Scores.some_order <= 2 then '1_2' else '' end two,
        case when Scores.some_order <= 1 then '1_1' else '' end one
        FROM Scores
      ) Scores_Flagged
      group by seven, six, five, four, three, two, one
     )Scores_by_Omogeneous_Classes

    | tot_seven | tot_six | tot_five | tot_four | tot_three | tot_two | tot_one |
    |-----------|---------|----------|----------|-----------|---------|---------|
    |      2760 |    1710 |      730 |      730 |       170 |      90 |      90 |    
    -----------------------------------------------------------------------------

4.最后,让我们按每个类评估我们的预期值(在本例中为百分比)::

    select 
    Classes.Class,
        case 
          when Classes.Class = 7 
          then cast((Total_Scores_by_Omogeneous_Classes.tot_seven/Classes.Reference_Score) * 100 as decimal(5,2)) 
          when Classes.Class = 6 
          then cast((Total_Scores_by_Omogeneous_Classes.tot_six/Classes.Reference_Score) * 100 as decimal(5,2)) 
          when Classes.Class = 5 
          then cast((Total_Scores_by_Omogeneous_Classes.tot_five/Classes.Reference_Score) * 100 as decimal(5,2)) 
          when Classes.Class = 4 
          then cast((Total_Scores_by_Omogeneous_Classes.tot_four/Classes.Reference_Score) * 100 as decimal(5,2)) 
          when Classes.Class = 3 
          then cast((Total_Scores_by_Omogeneous_Classes.tot_three/Classes.Reference_Score) * 100 as decimal(5,2)) 
          when Classes.Class = 2 
          then cast((Total_Scores_by_Omogeneous_Classes.tot_two/Classes.Reference_Score) * 100 as decimal(5,2)) 
          when Classes.Class = 1
          then cast((Total_Scores_by_Omogeneous_Classes.tot_one/Classes.Reference_Score) * 100 as decimal(5,2)) 
          else 0 
        end Percentage_Score
    from Classes
    inner join 
    (
      select 
        sum(Scores_by_Omogeneous_Classes.tot_seven) tot_seven,
        sum(Scores_by_Omogeneous_Classes.tot_six) tot_six,
        sum(Scores_by_Omogeneous_Classes.tot_five) tot_five,
        sum(Scores_by_Omogeneous_Classes.tot_four) tot_four,
        sum(Scores_by_Omogeneous_Classes.tot_three) tot_three,
        sum(Scores_by_Omogeneous_Classes.tot_two) tot_two,
        sum(Scores_by_Omogeneous_Classes.tot_one) tot_one
        from
        (
          select
          case when Scores_Flagged.seven = '1_7' then sum(Scores_Flagged.order_score) else 0 end tot_seven,
          case when Scores_Flagged.six   = '1_6' then sum(Scores_Flagged.order_score) else 0 end tot_six,
          case when Scores_Flagged.five  = '1_5' then sum(Scores_Flagged.order_score) else 0 end tot_five,
          case when Scores_Flagged.four  = '1_4' then sum(Scores_Flagged.order_score) else 0 end tot_four,
          case when Scores_Flagged.three = '1_3' then sum(Scores_Flagged.order_score) else 0 end tot_three,
          case when Scores_Flagged.two   = '1_2' then sum(Scores_Flagged.order_score) else 0 end tot_two,
          case when Scores_Flagged.one   = '1_1' then sum(Scores_Flagged.order_score) else 0 end tot_one
          from
          (
            select
            Scores.some_order, Scores.order_score,
            case when Scores.some_order <= 7 then '1_7' else '' end seven,
            case when Scores.some_order <= 6 then '1_6' else '' end six,
            case when Scores.some_order <= 5 then '1_5' else '' end five,
            case when Scores.some_order <= 4 then '1_4' else '' end four,
            case when Scores.some_order <= 3 then '1_3' else '' end three,
            case when Scores.some_order <= 2 then '1_2' else '' end two,
            case when Scores.some_order <= 1 then '1_1' else '' end one
            FROM Scores
          ) Scores_Flagged
          group by seven, six, five, four, three, two, one
         )Scores_by_Omogeneous_Classes
    ) Total_Scores_by_Omogeneous_Classes    

5.我们有我们参加的结果


| Class | Percentage_Score |
|-------|------------------|
|     1 |                5 |
|     3 |             9.44 |
|     5 |            40.56 |
|     7 |           153.33 |
----------------------------

我们还可以为相同的课程添加多个参考分数,因此可以根据更多参考分数产生多个百分比

for example:

 Class         Reference_Score 
----------------------------
   1              1800      
   3              1800      
   5              1800      
   7              1800      
   1              3600      
   3              3600      
   5              3600      
   7              3600    


 --------------------------
| Class | Percentage_Score |
|-------|------------------|
|     1 |                5 |
|     3 |             9.44 |
|     5 |            40.56 |
|     7 |           153.33 |
|     1 |              2.5 |
|     3 |             4.72 |
|     5 |            20.28 |
|     7 |            76.67 |       
----------------------------

【讨论】:

以上是关于如何使用 SQL 聚合一些概念类的值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL 中选择像 IF 这样的值?

如何在一个值之前的值上计算聚合函数 COUNT(DISTINCT)?

如何使用 postgresql 按多列中表示的值进行聚合

如何聚合熊猫系列的值

如何使用单个 SQL 聚合函数查询为同一个聚合函数获取多个结果?

如何选择 n 列和一个 SUM,同时仅按一些非聚合列分组?