{"id":1050,"date":"2009-07-28T14:38:08","date_gmt":"2009-07-28T12:38:08","guid":{"rendered":"http:\/\/code.openark.org\/blog\/?p=1050"},"modified":"2009-07-28T14:38:08","modified_gmt":"2009-07-28T12:38:08","slug":"auto-scaling-scaled-sql-graphs-concluded","status":"publish","type":"post","link":"https:\/\/code.openark.org\/blog\/mysql\/auto-scaling-scaled-sql-graphs-concluded","title":{"rendered":"Auto scaling, scaled SQL graphs concluded"},"content":{"rendered":"<p>I wasn&#8217;t sure I was to go this far. After catching breath the following have been added to <a href=\"http:\/\/code.openark.org\/blog\/mysql\/generic-auto-scaling-scaled-sql-graphs\">Generic, auto scaling, scaled SQL graphs<\/a>, and these will conclude my current hacks:<\/p>\n<ul>\n<li>Displaying X-axis min\/max values.<\/li>\n<li>Support for Y-axis values precision.<\/li>\n<li>Support for pre-defined scale range.<\/li>\n<\/ul>\n<p>The addition of the above makes for presentable, usable graphs. See also sample graphs at the end of this post.<\/p>\n<h4>Step 8: adding X-axis values<\/h4>\n<p>I add minimum\/maximum X-scale values to the graph. What was just <strong>ordering_column<\/strong> before, now turns to be the <strong>x<\/strong> in the <strong>y = f(x)<\/strong> function.<!--more--><\/p>\n<blockquote>\n<pre>SELECT\r\n  y_scale,\r\n  horizontal_bar\r\n  FROM\r\n  (\r\n  SELECT\r\n    @row_number := @row_number+1,\r\n    CASE @row_number\r\n      WHEN 1 THEN ROUND(max_value)\r\n      WHEN (@graph_rows+1)\/2 THEN ROUND((max_value+min_value)\/2)\r\n      WHEN @graph_rows THEN ROUND(min_value)\r\n      ELSE '~'\r\n    END AS y_scale,\r\n    horizontal_bar,\r\n    <strong>@bar_length := IFNULL(@bar_length, CHAR_LENGTH(horizontal_bar))<\/strong>\r\n  FROM\r\n    (SELECT @row_number := 0) AS select_row\r\n    INNER JOIN\r\n    (\r\n    SELECT\r\n      min_value,\r\n      max_value,\r\n      value_column,\r\n      GROUP_CONCAT(SUBSTRING(graph_bar, tinyint_asc.value, 1) ORDER BY ordering_column SEPARATOR '') AS horizontal_bar\r\n    FROM\r\n      (SELECT @row_number := 0) AS select_row,\r\n      tinyint_asc\r\n    INNER JOIN (\r\n      SELECT\r\n        ordering_column,\r\n        @min_value AS min_value,\r\n        @max_value AS max_value,\r\n        value_column,\r\n        @scaled_value := CONVERT((value_column-@min_value)*(@graph_rows-1)\/(@max_value-@min_value), UNSIGNED) AS scaled_value,\r\n        CONCAT(REPEAT('-',@scaled_value),'#',REPEAT('-',(@graph_rows-1)-@scaled_value)) AS graph_bar\r\n      FROM\r\n        (\r\n        SELECT\r\n          @min_value := LEAST(IFNULL(@min_value, value_column), value_column) AS min_value,\r\n          @max_value := GREATEST(IFNULL(@max_value, value_column), value_column) AS max_value,\r\n          <strong>@min_range := LEAST(IFNULL(@min_range, ordering_column), ordering_column) AS min_range<\/strong>,\r\n          <strong>@max_range := GREATEST(IFNULL(@max_range, ordering_column), ordering_column) AS max_range<\/strong>,\r\n          ordering_column,\r\n          value_column\r\n        FROM\r\n          (\r\n            SELECT id AS ordering_column, val AS value_column\r\n            FROM sample_values LIMIT 100\r\n          ) AS value_select,\r\n          (SELECT @min_value := NULL) AS select_min,\r\n          (SELECT @max_value := NULL) AS select_max,\r\n          <strong>(SELECT @min_range := NULL) AS select_min_range<\/strong>,\r\n          <strong>(SELECT @max_range := NULL) AS select_max_range<\/strong>,\r\n          <strong>(SELECT @bar_length := NULL) AS select_bar_length<\/strong>,\r\n          (SELECT @graph_rows := 15) AS select_graph_rows\r\n        ) AS select_range\r\n      ) AS select_vertical\r\n    WHERE\r\n      tinyint_asc.value BETWEEN 1 AND CHAR_LENGTH(graph_bar)\r\n    GROUP BY\r\n      tinyint_asc.value\r\n    ORDER BY\r\n      tinyint_asc.value DESC\r\n    ) AS select_horizontal\r\n  ) AS select_horizontal_untitled\r\n<strong>UNION ALL<\/strong>\r\n<strong>SELECT '', CONCAT('v', REPEAT(':', @bar_length-2), 'v')<\/strong>\r\n<strong>UNION ALL<\/strong>\r\n<strong>SELECT '', CONCAT(@min_range, REPEAT(' ', @bar_length-CHAR_LENGTH(@min_range)-CHAR_LENGTH(@max_range)), @max_range)<\/strong>\r\n;\r\n+---------+------------------------------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                                       |\r\n+---------+------------------------------------------------------------------------------------------------------+\r\n| 2       | ------------########-------------------------------------------------------########----------------- |\r\n| ~       | ----------##--------###-------------------------------------------------###--------###-------------- |\r\n| ~       | -------###-------------##---------------------------------------------##--------------##------------ |\r\n| ~       | ------#------------------##------------------------------------------#------------------##---------- |\r\n| ~       | ----##---------------------#---------------------------------------##---------------------#--------- |\r\n| ~       | ---#------------------------##-----------------------------------##------------------------##------- |\r\n| ~       | -##---------------------------#---------------------------------#----------------------------#------ |\r\n| 1       | #------------------------------##------------------------------#------------------------------#----- |\r\n| ~       | ---------------------------------#---------------------------##--------------------------------##--- |\r\n| ~       | ----------------------------------##------------------------#------------------------------------#-- |\r\n| ~       | ------------------------------------#---------------------##--------------------------------------## |\r\n| ~       | -------------------------------------##-----------------##------------------------------------------ |\r\n| ~       | ---------------------------------------##-------------##-------------------------------------------- |\r\n| ~       | -----------------------------------------###-------###---------------------------------------------- |\r\n| 0       | --------------------------------------------#######------------------------------------------------- |\r\n|         | v::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 0                                                                                                 99 |\r\n+---------+------------------------------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<p>The X-axis range is <strong>[0..99]<\/strong>, displayed below. The code does not limit us to <strong>INTEGER<\/strong>. We may as well have <strong>FLOAT<\/strong>, <strong>DATE<\/strong>, <strong>TIMESTAMP<\/strong> etc. (examples follow).<\/p>\n<h4>Step 9: adding precision<\/h4>\n<p>The <strong>0,1,2<\/strong> Y-axis values play nicely here. But if my generic query is:<\/p>\n<blockquote>\n<pre>SELECT id AS ordering_column, val\/3 AS value_column FROM sample_values LIMIT 100<\/pre>\n<\/blockquote>\n<p>The resulting graph looks like:<\/p>\n<blockquote>\n<pre>+---------+------------------------------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                                       |\r\n+---------+------------------------------------------------------------------------------------------------------+\r\n| 1       | ------------#########------------------------------------------------------#########---------------- |\r\n| ~       | --------####---------###-----------------------------------------------####---------###------------- |\r\n| ~       | ------##----------------###------------------------------------------##----------------###---------- |\r\n| ~       | ----##---------------------##-------------------------------------###---------------------##-------- |\r\n| ~       | -###-------------------------##---------------------------------##--------------------------##------ |\r\n| 0       | #------------------------------##-----------------------------##------------------------------##---- |\r\n| ~       | ---------------------------------##-------------------------##----------------------------------##-- |\r\n| ~       | -----------------------------------##---------------------##--------------------------------------## |\r\n| ~       | -------------------------------------###----------------##------------------------------------------ |\r\n| ~       | ----------------------------------------###---------####-------------------------------------------- |\r\n| 0       | -------------------------------------------#########------------------------------------------------ |\r\n|         | v::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 0                                                                                                 99 |\r\n+---------+------------------------------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<p>And the <strong>0,0,1<\/strong> values are completely inappropriate. We will now introduce precision:<\/p>\n<blockquote>\n<pre>SELECT\r\n  y_scale,\r\n  horizontal_bar\r\n  FROM\r\n  (\r\n  SELECT\r\n    @row_number := @row_number+1,\r\n    CASE @row_number\r\n      WHEN 1 THEN <strong>ROUND(max_value * POW(10, @value_precision))\/POW(10, @value_precision)<\/strong>\r\n      WHEN (@graph_rows+1)\/2 THEN <strong>ROUND((max_value+min_value)*POW(10, @value_precision)\/2)\/POW(10, @value_precision)<\/strong>\r\n      WHEN @graph_rows THEN <strong>ROUND(min_value*POW(10, @value_precision))\/POW(10, @value_precision)<\/strong>\r\n      ELSE '~'\r\n    END AS y_scale,\r\n    horizontal_bar,\r\n    @bar_length := IFNULL(@bar_length, CHAR_LENGTH(horizontal_bar))\r\n  FROM\r\n    (SELECT @row_number := 0) AS select_row\r\n    INNER JOIN\r\n    (\r\n    SELECT\r\n      min_value,\r\n      max_value,\r\n      value_column,\r\n      GROUP_CONCAT(SUBSTRING(graph_bar, tinyint_asc.value, 1) ORDER BY ordering_column SEPARATOR '') AS horizontal_bar\r\n    FROM\r\n      (SELECT @row_number := 0) AS select_row,\r\n      tinyint_asc\r\n    INNER JOIN (\r\n      SELECT\r\n        ordering_column,\r\n        @min_value AS min_value,\r\n        @max_value AS max_value,\r\n        value_column,\r\n        @scaled_value := CONVERT((value_column-@min_value)*(@graph_rows-1)\/(@max_value-@min_value), UNSIGNED) AS scaled_value,\r\n        CONCAT(REPEAT('-',@scaled_value),'#',REPEAT('-',(@graph_rows-1)-@scaled_value)) AS graph_bar\r\n      FROM\r\n        (\r\n        SELECT\r\n          @min_value := LEAST(IFNULL(@min_value, value_column), value_column) AS min_value,\r\n          @max_value := GREATEST(IFNULL(@max_value, value_column), value_column) AS max_value,\r\n          @min_range := LEAST(IFNULL(@min_range, ordering_column), ordering_column) AS min_range,\r\n          @max_range := GREATEST(IFNULL(@max_range, ordering_column), ordering_column) AS max_range,\r\n          ordering_column,\r\n          value_column\r\n        FROM\r\n          (\r\n            SELECT id AS ordering_column, val\/3 AS value_column\r\n            FROM sample_values LIMIT 100\r\n          ) AS value_select,\r\n          (SELECT @min_value := NULL) AS select_min,\r\n          (SELECT @max_value := NULL) AS select_max,\r\n          (SELECT @min_range := NULL) AS select_min_range,\r\n          (SELECT @max_range := NULL) AS select_max_range,\r\n          (SELECT @bar_length := NULL) AS select_bar_length,\r\n          <strong>(SELECT @value_precision := 2) AS select_value_precision,<\/strong>\r\n          (SELECT @graph_rows := 15) AS select_graph_rows\r\n        ) AS select_range\r\n      ) AS select_vertical\r\n    WHERE\r\n      tinyint_asc.value BETWEEN 1 AND CHAR_LENGTH(graph_bar)\r\n    GROUP BY\r\n      tinyint_asc.value\r\n    ORDER BY\r\n      tinyint_asc.value DESC\r\n    ) AS select_horizontal\r\n  ) AS select_horizontal_untitled\r\nUNION ALL\r\nSELECT '', CONCAT('v', REPEAT(':', @bar_length-2), 'v')\r\nUNION ALL\r\nSELECT '', CONCAT(@min_range, REPEAT(' ', @bar_length-CHAR_LENGTH(@min_range)-CHAR_LENGTH(@max_range)), @max_range)\r\n;\r\n+---------+------------------------------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                                       |\r\n+---------+------------------------------------------------------------------------------------------------------+\r\n| 0.67    | ------------########-------------------------------------------------------########----------------- |\r\n| ~       | ----------##--------###-------------------------------------------------###--------###-------------- |\r\n| ~       | -------###-------------##---------------------------------------------##--------------##------------ |\r\n| ~       | ------#------------------##------------------------------------------#------------------##---------- |\r\n| ~       | ----##---------------------#---------------------------------------##---------------------#--------- |\r\n| ~       | ---#------------------------##-----------------------------------##------------------------##------- |\r\n| ~       | -##---------------------------#---------------------------------#----------------------------#------ |\r\n| 0.33    | #------------------------------##------------------------------#------------------------------#----- |\r\n| ~       | ---------------------------------#---------------------------##--------------------------------##--- |\r\n| ~       | ----------------------------------##------------------------#------------------------------------#-- |\r\n| ~       | ------------------------------------#---------------------##--------------------------------------## |\r\n| ~       | -------------------------------------##-----------------##------------------------------------------ |\r\n| ~       | ---------------------------------------##-------------##-------------------------------------------- |\r\n| ~       | -----------------------------------------###-------###---------------------------------------------- |\r\n| 0       | --------------------------------------------#######------------------------------------------------- |\r\n|         | v::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 0                                                                                                 99 |\r\n+---------+------------------------------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<p>Watch the <strong>0.33, 0.67<\/strong> values generated here. This is much better.<\/p>\n<h4>Step 10: setting fixed scale range<\/h4>\n<p>When we compare two graphs, it&#8217;s best if they are scaled the same way. So far, our graphs have scaled automatically according to min\/max values. What we add now is a way to predefine the range. For example, dealing with <strong>per-cent<\/strong> values, I may always wish to scale <strong>[0..100]<\/strong>, regardless of min\/max values.<\/p>\n<p>The code below defines a scale of <strong>[-1, 1]<\/strong>. It <em>automatically extends<\/em> if the range is actually insufficient, so it&#8217;s safe to use. Let&#8217;s see the same last graph again:<\/p>\n<blockquote>\n<pre>SELECT\r\n  y_scale,\r\n  horizontal_bar\r\n  FROM\r\n  (\r\n  SELECT\r\n    @row_number := @row_number+1,\r\n    CASE @row_number\r\n      WHEN 1 THEN ROUND(max_value * POW(10, @value_precision))\/POW(10, @value_precision)\r\n      WHEN (@graph_rows+1)\/2 THEN ROUND((max_value+min_value)*POW(10, @value_precision)\/2)\/POW(10, @value_precision)\r\n      WHEN @graph_rows THEN ROUND(min_value*POW(10, @value_precision))\/POW(10, @value_precision)\r\n      ELSE '~'\r\n    END AS y_scale,\r\n    horizontal_bar,\r\n    @bar_length := IFNULL(@bar_length, CHAR_LENGTH(horizontal_bar))\r\n  FROM\r\n    (SELECT @row_number := 0) AS select_row\r\n    INNER JOIN\r\n    (\r\n    SELECT\r\n      min_value,\r\n      max_value,\r\n      value_column,\r\n      GROUP_CONCAT(SUBSTRING(graph_bar, tinyint_asc.value, 1) ORDER BY ordering_column SEPARATOR '') AS horizontal_bar\r\n    FROM\r\n      (SELECT @row_number := 0) AS select_row,\r\n      tinyint_asc\r\n    INNER JOIN (\r\n      SELECT\r\n        ordering_column,\r\n        @min_value AS min_value,\r\n        @max_value AS max_value,\r\n        value_column,\r\n        @scaled_value := CONVERT((value_column-@min_value)*(@graph_rows-1)\/(@max_value-@min_value), UNSIGNED) AS scaled_value,\r\n        CONCAT(REPEAT('-',@scaled_value),'#',REPEAT('-',(@graph_rows-1)-@scaled_value)) AS graph_bar\r\n      FROM\r\n        (\r\n        SELECT\r\n          @min_value := LEAST(<strong>IFNULL(@min_scale_value, value_column),<\/strong> IFNULL(@min_value, value_column), value_column) AS min_value,\r\n          @max_value := GREATEST(<strong>IFNULL(@max_scale_value, value_column),<\/strong> IFNULL(@max_value, value_column), value_column) AS max_value,\r\n          @min_range := LEAST(IFNULL(@min_range, ordering_column), ordering_column) AS min_range,\r\n          @max_range := GREATEST(IFNULL(@max_range, ordering_column), ordering_column) AS max_range,\r\n          ordering_column,\r\n          value_column\r\n        FROM\r\n          (\r\n            SELECT id AS ordering_column, val\/3 AS value_column FROM sample_values LIMIT 100\r\n          ) AS value_select,\r\n          (SELECT @min_value := NULL) AS select_min,\r\n          (SELECT @max_value := NULL) AS select_max,\r\n          (SELECT @min_range := NULL) AS select_min_range,\r\n          (SELECT @max_range := NULL) AS select_max_range,\r\n          (SELECT @bar_length := NULL) AS select_bar_length,\r\n          <strong>(SELECT @min_scale_value := -1) AS select_min_scale,<\/strong>\r\n          <strong>(SELECT @max_scale_value := 1) AS select_max_scale,<\/strong>\r\n          (SELECT @value_precision := 2) AS select_value_precision,\r\n          (SELECT @graph_rows := 15) AS select_graph_rows\r\n        ) AS select_range\r\n      ) AS select_vertical\r\n    WHERE\r\n      tinyint_asc.value BETWEEN 1 AND CHAR_LENGTH(graph_bar)\r\n    GROUP BY\r\n      tinyint_asc.value\r\n    ORDER BY\r\n      tinyint_asc.value DESC\r\n    ) AS select_horizontal\r\n  ) AS select_horizontal_untitled\r\nUNION ALL\r\nSELECT '', CONCAT('v', REPEAT(':', @bar_length-2), 'v')\r\nUNION ALL\r\nSELECT '', CONCAT(@min_range, REPEAT(' ', @bar_length-CHAR_LENGTH(@min_range)-CHAR_LENGTH(@max_range)), @max_range)\r\n;\r\n+---------+------------------------------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                                       |\r\n+---------+------------------------------------------------------------------------------------------------------+\r\n| 1       | ---------------------------------------------------------------------------------------------------- |\r\n| ~       | ---------------------------------------------------------------------------------------------------- |\r\n| ~       | ------------########-------------------------------------------------------########----------------- |\r\n| ~       | ------######--------#######------------------------------------------######--------#######---------- |\r\n| ~       | -#####---------------------####---------------------------------#####---------------------####------ |\r\n| ~       | #------------------------------#####------------------------####------------------------------####-- |\r\n| ~       | ------------------------------------#####-------------######--------------------------------------## |\r\n| 0       | -----------------------------------------#############---------------------------------------------- |\r\n| ~       | ---------------------------------------------------------------------------------------------------- |\r\n| ~       | ---------------------------------------------------------------------------------------------------- |\r\n| ~       | ---------------------------------------------------------------------------------------------------- |\r\n| ~       | ---------------------------------------------------------------------------------------------------- |\r\n| ~       | ---------------------------------------------------------------------------------------------------- |\r\n| ~       | ---------------------------------------------------------------------------------------------------- |\r\n| -1      | ---------------------------------------------------------------------------------------------------- |\r\n|         | v::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 0                                                                                                 99 |\r\n+---------+------------------------------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<p>Values are still in range <strong>[0..0.667]<\/strong>, but are presented on a wider scale.<\/p>\n<h4>Showcase<\/h4>\n<p>Here are some nice graphs generated, to show off.<\/p>\n<blockquote>\n<pre>+---------+----------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                   |\r\n+---------+----------------------------------------------------------------------------------+\r\n| 14.17   | ----------------------------------------------------------------------###------- |\r\n| ~       | ---------------------------------------------------------------------#---#------ |\r\n| ~       | --------------------------------------------------------------------#-----#----- |\r\n| ~       | -------------------------------------------------------##----------------------- |\r\n| ~       | -----------------------------------------------------##--#---------#-------#---- |\r\n| ~       | ----------------------------------------------------#-----#--------------------- |\r\n| ~       | ---------------------------------------###-----------------#------#------------- |\r\n| 7.09    | -------------------------------------##---#--------#------------------------#--- |\r\n| ~       | ------------------------------------#------#----------------#------------------- |\r\n| ~       | -----------------------####--------#--------#-----#--------------#-----------#-- |\r\n| ~       | ---------------------##----#-----------------#---#-----------#------------------ |\r\n| ~       | --------------------#-------##----#-----------------------------#--------------- |\r\n| ~       | --------#####-----##----------#--#------------#-#-------------#---------------#- |\r\n| ~       | ----####-----##--#-------------##----------------------------------------------# |\r\n| 0       | ####-----------##------------------------------#---------------#---------------- |\r\n|         | v::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 2009-07-25 21:43:27                                          2009-07-29 06:02:27 |\r\n+---------+----------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<blockquote>\n<pre>+---------+---------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                  |\r\n+---------+---------------------------------------------------------------------------------+\r\n| 0.99    | ##----------------------------------------------------------------------------- |\r\n| ~       | --##--------------------------------------------------------------------------- |\r\n| ~       | ----#-------------------------------------------------------------------------- |\r\n| ~       | -----##------------------------------------------------------------------------ |\r\n| ~       | -------#----------------------------------------------------------------------- |\r\n| ~       | --------#---------------------------------------------------------------------- |\r\n| ~       | ---------#--------------------------------------------------------------------- |\r\n| 0.39    | ----------#-------------------------------------------------------------------- |\r\n| ~       | -----------#------------------------------------------------------------------- |\r\n| ~       | ------------#------------------------------------------------------------------ |\r\n| ~       | -------------#--------------------########------------------------------------- |\r\n| ~       | --------------#----------------###--------#####---------------################- |\r\n| ~       | ---------------##-----------###----------------#####----######----------------# |\r\n| ~       | -----------------##------###------------------------####----------------------- |\r\n| -0.22   | -------------------######------------------------------------------------------ |\r\n|         | v:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 2009-07-25 21:43:27                                         2009-07-29 06:02:27 |\r\n+---------+---------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<blockquote>\n<pre>+---------+---------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                  |\r\n+---------+---------------------------------------------------------------------------------+\r\n| -0      | --------------------######################------------------------------------- |\r\n| ~       | ------------########----------------------#######--------------------------#### |\r\n| ~       | --------####-------------------------------------#####-----------------####---- |\r\n| ~       | ------##----------------------------------------------##------------###-------- |\r\n| ~       | ----##--------------------------------------------------##---------#----------- |\r\n| ~       | ---#------------------------------------------------------#------##------------ |\r\n| ~       | --#--------------------------------------------------------#------------------- |\r\n| -2.39   | -#----------------------------------------------------------#---#-------------- |\r\n| ~       | ---------------------------------------------------------------#--------------- |\r\n| ~       | #------------------------------------------------------------#----------------- |\r\n| ~       | ------------------------------------------------------------------------------- |\r\n| ~       | ------------------------------------------------------------------------------- |\r\n| ~       | ------------------------------------------------------------------------------- |\r\n| ~       | ------------------------------------------------------------------------------- |\r\n| -4.78   | --------------------------------------------------------------#---------------- |\r\n|         | v:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 0                                                                          3.95 |\r\n+---------+---------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<blockquote>\n<pre>+---------+----------------------------------------------------------------------------------+\r\n| y_scale | horizontal_bar                                                                   |\r\n+---------+----------------------------------------------------------------------------------+\r\n| 110.82  | ---------------------------------------------------oooooo----------------------- |\r\n| ~       | ------------------------------------------------ooooooooooo--------------------- |\r\n| ~       | ----------------------------------------------oooooooooooooo-------------------- |\r\n| ~       | --------------------------------------------oooooooooooooooooo------------------ |\r\n| ~       | ----------------------------------oooo----ooooooooooooooooooooo----------------- |\r\n| ~       | o------------------------------ooooooooooooooooooooooooooooooooo---------------- |\r\n| ~       | o----------------------------ooooooooooooooooooooooooooooooooooo---------------- |\r\n| ~       | oo--------------------------ooooooooooooooooooooooooooooooooooooo--------------- |\r\n| ~       | oo-------------------------ooooooooooooooooooooooooooooooooooooooo-------------- |\r\n| ~       | ooo-----------------------ooooooooooooooooooooooooooooooooooooooooo------------- |\r\n| ~       | oooo--------------------oooooooooooooooooooooooooooooooooooooooooooo------------ |\r\n| ~       | oooo-------------------ooooooooooooooooooooooooooooooooooooooooooooo------------ |\r\n| 85.93   | ooooo-----------------ooooooooooooooooooooooooooooooooooooooooooooooo----------- |\r\n| ~       | oooooo---------------ooooooooooooooooooooooooooooooooooooooooooooooooo---------- |\r\n| ~       | ooooooo-------------oooooooooooooooooooooooooooooooooooooooooooooooooo---------- |\r\n| ~       | oooooooo-----------oooooooooooooooooooooooooooooooooooooooooooooooooooo--------- |\r\n| ~       | ooooooooo--------ooooooooooooooooooooooooooooooooooooooooooooooooooooooo-------- |\r\n| ~       | ooooooooooo----oooooooooooooooooooooooooooooooooooooooooooooooooooooooooo------- |\r\n| ~       | ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo------- |\r\n| ~       | oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo------ |\r\n| ~       | ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo----- |\r\n| ~       | oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo---- |\r\n| ~       | ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo--- |\r\n| ~       | oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo-- |\r\n| 61.04   | oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo |\r\n|         | v::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::v |\r\n|         | 93                                                                           172 |\r\n+---------+----------------------------------------------------------------------------------+<\/pre>\n<\/blockquote>\n<h4>Why?<\/h4>\n<p>Why go for all this trouble? Isn&#8217;t this nothing but a cool hack?<\/p>\n<p>Is this stuff useful? Practical?<\/p>\n<p>I have some agenda with this, which I&#8217;ll be happy to share when comes into being. I think there are very practical uses for SQL-based graphs. I&#8217;m sure many readers can think of interesting uses, other than the ones I have in mind.<\/p>\n<h4>Conclusion<\/h4>\n<p>There are many more possibilities and featured which can be built into the graphs. I&#8217;m going to stop here, before this becomes too picky. I hope I have shown that some very nice graphs can be produced with SQL alone.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wasn&#8217;t sure I was to go this far. After catching breath the following have been added to Generic, auto scaling, scaled SQL graphs, and these will conclude my current hacks: Displaying X-axis min\/max values. Support for Y-axis values precision. Support for pre-defined scale range. The addition of the above makes for presentable, usable graphs. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[5],"tags":[41,21],"class_list":["post-1050","post","type-post","status-publish","format-standard","hentry","category-mysql","tag-graphs","tag-sql"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2bZZp-gW","_links":{"self":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/1050","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/comments?post=1050"}],"version-history":[{"count":35,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/1050\/revisions"}],"predecessor-version":[{"id":1091,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/1050\/revisions\/1091"}],"wp:attachment":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/media?parent=1050"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/categories?post=1050"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/tags?post=1050"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}