计算某些列值的百分比并将其添加到新列

时间:2016-11-10 08:20:34

标签: sql select group-by common-table-expression

我有一张下表

[Table_OrangeIsNewBlack]
ID  |   Name    |   Color   |   RedPercent
------------------------------------------
1   |   Donald  |   Orange  |   
2   |   Hillary |   White   |   
3   |   Barack  |   Black   |   
4   |   Bernie  |   Grey    |   
1   |   Donald  |   Red     |   
2   |   Hillary |   Red     |   
3   |   Barack  |   Black   |   
4   |   Bernie  |   Grey    |   
1   |   Donald  |   Red     |   
2   |   Hillary |   Blue    |   
3   |   Barack  |   Red     |   
4   |   Bernie  |   Purple  |   

我需要添加一个百分比值,以显示此人的频率'红色'

唐纳德的记录

1       Donald      Orange      
1       Donald      Red         
1       Donald      Red         

RedPercent:(2/3)* 100 = 66,66

希拉里

2       Hillary     White       
2       Hillary     Red         
2       Hillary     Blue        

'蓝色'和'紫色'不要算,因此:

RedPercent:(1/2)* 100 = 50,00

美国总统

3       Barack      Black       
3       Barack      Black       
3       Barack      Red

RedPercent:(1/3)* 100 = 33,33

伯尼

4       Bernie      Grey        
4       Bernie      Blue        
4       Bernie      Purple      

'蓝色'和'紫色'不计算

RedPercent:(0/1)* 100 = 00,00

需要的结果:

[Table_OrangeIsNewBlack]
ID  |   Name    |   Color   |   RedPercent
------------------------------------------
1   |   Donald  |   Orange  |   66,66
2   |   Hillary |   White   |   50,00
3   |   Barack  |   Black   |   33,33
4   |   Bernie  |   Grey    |   00,00
1   |   Donald  |   Red     |   66,66
2   |   Hillary |   Red     |   50,00
3   |   Barack  |   Black   |   33,33
4   |   Bernie  |   Grey    |   00,00
1   |   Donald  |   Red     |   66,66
2   |   Hillary |   Blue    |   50,00
3   |   Barack  |   Red     |   33,33
4   |   Bernie  |   Purple  |   00,00

我试过了:

;WITH CTE AS
    (
        SELECT  ID, 
                    -- Division: count of Reds  / count of persons all rows 
                    ((SELECT COUNT(ID) FROM Table_OrangeIsNewBlack
                    WHERE Color = 'Red' )
                    /       
                    (SELECT COUNT(ID) FROM Table_OrangeIsNewBlack
                    WHERE ( Color  <> 'Blue' and
                            Color  <> 'Purple' ))
                    )
                    AS redprcnt
                -- end of Division
        FROM Table_OrangeIsNewBlack
    )
    UPDATE T1
        SET RedPercent = CTE.redprcnt
        FROM Table_OrangeIsNewBlack T1 
    INNER JOIN CTE ON(T1.ID = CTE.ID)

SELECT子句......

SELECT  ID, 
            -- Division: count of Reds  / count of persons all rows 
            ((SELECT COUNT(ID) FROM Table_OrangeIsNewBlack
            WHERE Color = 'Red' )
            /       
            (SELECT COUNT(ID) FROM Table_OrangeIsNewBlack
            WHERE ( Color  <> 'Blue' and
                    Color  <> 'Purple' ))
            )
            AS redprcnt
        -- end of Division
FROM Table_OrangeIsNewBlack

...只为redprcnt

提供零

我应该在某个时候使用GROUP BY吗?

有什么建议吗?

提前致谢。

2 个答案:

答案 0 :(得分:1)

COUNT通常会生成INTEGER,因此COUNT/COUNT是一个整数除法,它会截断,您的基本查询会尝试计算整体百分比,而不是每组的%。

此外,您可以使用条件聚合简化计算:

SELECT ID,
        -- Division: count of Reds  / count of persons all rows 
   100.00 * COUNT(CASE WHEN Color = 'Red' THEN ID END)
          / NULLIF(COUNT(CASE WHEN Color  <> 'Blue' and Color  <> 'Purple'  THEN ID END), 0) AS redprcnt
FROM Table_OrangeIsNewBlack
GROUP BY ID

对于不计数的非匹配行,CASE返回NULL。

编辑:

如果您确实需要重复每行的百分比,则可以改为 Windowed Aggregate

SELECT ID, Name, Color, 
   100.00 * Count(CASE WHEN Color = 'Red' THEN ID END) Over(PARTITION BY NAME)
          / NULLIF(Count(CASE WHEN Color  <> 'Blue' AND Color  <> 'Purple'  THEN ID END) Over(PARTITION BY NAME), 0) AS redprcnt
 FROM Table_OrangeIsNewBlack

答案 1 :(得分:1)

有趣的任务,我制作了可以帮助你的脚本

;WITH CTE AS
(
  SELECT * ,COUNT(CASE WHEN Color = 'Red' THEN ID END) OVER(Partition by Name,Color) ColorCount,
            COUNT(CASE WHEN Color  <> 'Blue' and Color  <> 'Purple'  THEN ID END)  OVER(Partition by Name)TotalCount
  FROM TableName
)
SELECT ID,Name, (SELECT MAX(((ColorCount*1.0)/(CASE WHEN TotalCount = 0 THEN 1 ELSE TotalCount END))*100) 
                 FROM CTE InnerCte 
                 WHERE OuterCTE.ID=InnerCte.ID AND OuterCTE.Name=InnerCte.Name )
FROM CTE OuterCTE