如何将某些概念性 类 的值与 SQL 相加?

How do I aggregate values respect to some conceptual classes with SQL?

我想解决的问题是class化一些值以通过SQL提取一些知识。

它要提出的sql解决方案可以应用于由少数classes

组成的class化系统

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

class的数量应该非常有限。

例如:class由所有小于七的天组成,class由所有小于六的天组成, class 由小于五的所有天组成,依此类推...

我的灵感来自一个关于堆栈溢出的问题.. Aggregation of Data

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

基于 SQL

中的 class化系统的价值聚合

为了解决这类问题,在我们的问题中定义了约束,我们可以开始考虑我们的 class化系统将包含一些 table 记录,代表我们将考虑的 classes 执行我们的计算,我们的参考系统。

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

那么,让我们创建 table 个 classes..

Table"Classes"的问题。

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

此 table 的每条记录表示小于字段值 "Class":

的所有值的 class

..然后是我们的 "Scores"

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

ok..我们想知道每个 class 的百分比分数,即所有分数总和的关系 属于class,分数分配给class,我们的参考分数:

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




ok开始吧..(后面的sql是MySqldbms的实现)

1. the first thing is to assign flags to each value of our scores by order:

    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. now, we can start to calculate the sum of each score and put this sum in computed field, each of whom represents a class of our problem, and the table records we'll get out, represent the score by omogeneous class:

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. at this point, let'get the total scores for omogeneous classes, who they will be the basis of our compute:

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. and finally, let's evaluate our intedend value (in this case a percentage) by each class::

    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. We have our attended result:


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



We can also add multiple reference scores for the same classes, and so can have several percentages related upon more reference scores:

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 |       
----------------------------