Pie Charts

From PostgreSQL wiki
Jump to navigationJump to search

Fun Snippets

Pie Charts

Works with PostgreSQL

8.4

Written in

SQL

Depends on

Nothing


Based on the original idea by Shlomi Noach at http://code.openark.org/blog/mysql/sql-pie-chart

Change the "VALUES" subquery to use a different data set.

\set width  80
\set height 25
\set radius 1.0
\set colours '''#;o:X"@+-=123456789abcdef'''
WITH slices AS (
 SELECT  CAST(row_number() over () AS integer) AS slice,
         name, 
	 value,
	 100.0 * value / sum(value) OVER () AS percentage,
	 2*PI() * sum(value) OVER (rows unbounded preceding) 
                / sum(value) OVER () AS radians
   FROM (VALUES ('red',1),
                ('blue',2),
                ('orange',3),
                ('white',4)
        ) AS data(name,value))
(
  SELECT array_to_string(array_agg(c),'') AS pie_chart
    FROM (
    SELECT x, y,
           CASE WHEN NOT (sqrt(pow(x, 2) + pow(y, 2)) 
                            BETWEEN :radius*1/10 AND :radius)
                THEN ' '
                ELSE substring(:colours,
                               (select min(slice) 
                                  from slices 
                                 where radians >= PI() + atan2(y,-x)),
                               1)
                END AS c
      FROM (SELECT 2.0*generate_series(0,:width)/:width-1.0)   AS x(x),
           (SELECT 2.0*generate_series(0,:height)/:height-1.0) AS y(y)
     ORDER BY y,x
  ) AS xy
 GROUP BY y
 ORDER BY y
)
UNION ALL 
SELECT repeat(substring(:colours,slice,1), 2) || '  ' || 
       name || ': ' || 
       value || '  (' || round(percentage,0) || '%)' 
  FROM slices;

Result:

                                     pie_chart                                     
-----------------------------------------------------------------------------------
                                         ;                                        
                          oooo;;;;;;;;;;;;;;;;;;;;;;;;;;;                         
                    ooooooooooo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                   
                oooooooooooooooo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;               
            ooooooooooooooooooooo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;           
         ooooooooooooooooooooooooo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;        
       oooooooooooooooooooooooooooo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;######      
      oooooooooooooooooooooooooooooo;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;###########     
    ooooooooooooooooooooooooooooooooo;;;;;;;;;;;;;;;;;;;;;;;;##################   
   ooooooooooooooooooooooooooooooooooo;;;;;;;;;;;;;;;;;;;#######################  
  ooooooooooooooooooooooooooooooooooooo;;;;;;;;;;;;;;############################ 
  oooooooooooooooooooooooooooooooooooooo;;;;;;;;################################# 
  oooooooooooooooooooooooooooooooooooo       #################################### 
  oooooooooooooooooooooooooooooooooooo       :::::::::::::::::::::::::::::::::::: 
  ooooooooooooooooooooooooooooooooo:::::::::::::::::::::::::::::::::::::::::::::: 
  oooooooooooooooooooooooooooo::::::::::::::::::::::::::::::::::::::::::::::::::: 
   ooooooooooooooooooooooo::::::::::::::::::::::::::::::::::::::::::::::::::::::  
    oooooooooooooooooo:::::::::::::::::::::::::::::::::::::::::::::::::::::::::   
      ooooooooooo::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::     
       oooooo:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::      
         :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::        
            :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::           
                :::::::::::::::::::::::::::::::::::::::::::::::::::               
                    :::::::::::::::::::::::::::::::::::::::::::                   
                          :::::::::::::::::::::::::::::::                         
                                         :                                        
 ##  red: 1  (10%)
 ;;  blue: 2  (20%)
 oo  orange: 3  (30%)
 ::  white: 4  (40%)
(30 rows)