简体   繁体   中英

How to chart missing data in chartjs

The problem

I want to create a time based, stacked bar chart using Chartjs but I have missing time values. I have two questions:

1.) How can I fill in the missing data with zeroes either in the SQL query or while I am building the arrays from the Ajax response?

2.) Is there a better way to visualize the data using chartjs rather than using a stacked chart that does not require the missing data?

The following is a simple explanation summarized by month. In production, this could dynamically change to a weekly or daily summarization. Working example available on jsFiddle

The desired outcome:

+----+
|Bill|  +----+  +----+
|    |  |Bill|  |Bill|
|----|  |----|  +----+
|Joe |  |Mary|  |Mary|
+----+  +----+  +----+
 Jan     Feb     Mar

This is a hyper simplified version of the database table to illustrate the problem.

Orders table:
+--------+---------+-------+
|Salesman| Order # | Month |
+--------+---------+-------+
|Bill    | 10500   | Jan   |
|Bill    | 10501   | Jan   |
|Joe     | 10867   | Jan   |
|Mary    | 10892   | Feb   |
|Bill    | 12527   | Feb   |
|Mary    | 12741   | Mar   |
|Bill    | 13292   | Mar   |
+--------+---------+-------+
SELECT salesman, month, count(*) as orders
FROM orders
GROUP BY month, salesman
ORDER BY month, Salesman
+------+----------+--------+
|Month | Salesman | Orders |
+------+----------+--------+
|Jan   | Bill     | 2      |
|Jan   | Joe      | 1      |
|Feb   | Mary     | 1      |
|Feb   | Bill     | 1      |
|Mar   | Mary     | 1      |
|Mar   | Bill     | 1      |  
+------+----------+--------+

Mary has no entry for Jan and Joe has no entries for Feb or Mar. When I build the array from the ajax response, my chart.data.labels array for the x-values are [Jan, Feb, Mar] but the chart.datasets[n].data for the y-values look like this:

Bill : [2,1,1]
Joe : [1]
Mary: [1,1]

They should look like this:

Bill : [2,1,1]
Joe : [1,0,0]
Mary: [0,1,1]

@nbk provided the clue to the resolution with a pivot table. Here's my solution, a PHP function in the controller to dynamically build SQL for a pivot table.

Might move it to a general purpose utility lib in the future.

    private function pivotTable($table, $pivotColumn, $pivotLabel,  $whereClause, $aggregate="count"){
        $returnValue = [];

        // validate parms exist
        if ((isset($table) != true) ||
            (isset($pivotLabel) != true) ||
            (isset($pivotColumn) != true)) {
                $returnValue['error'] = true;
                $returnValue['message'] = 'Invalid parameter';
                return $returnValue ;
            }

        // build the SQL to get the column names and column count
        $qry =  "SELECT DISTINCT {$pivotColumn} FROM {$table} ";
        $where =    (isset($whereClause)) ? "WHERE {$whereClause} " : "";
        $order = "ORDER BY {$pivotColumn};";
        // execute the query
        $columns = $this->db->query($qry . $where . $order);

        // no columns  to pivot
        if( $columns->num_rows() < 1) {
            $returnValue['error'] = true;
            $returnValue['message'] = 'No columns to pivot';
            return $returnValue ;
        }

        // too many columns to pivot
        if($columns->num_rows() > 50) {
            $returnValue['error'] = true;
            $returnValue['message'] = 'Pivot would result in more than 50 columns';
            return $returnValue ;
        };

        // build pivot query
        $i = 0;
        $pivotQry = "SELECT {$pivotLabel} ";
        foreach($columns->result_array() as $column) {
            $pivotQry .= ",\r\n{$aggregate}( IF ( {$pivotColumn} = '{$column[$pivotColumn]}', {$pivotColumn}, NULL ) ) as  {$column[$pivotColumn]} ";
        }

        $pivotQry .= "\r\nFROM {$table} \r\n";
        $pivotQry .= $where;
        $pivotQry .= "GROUP BY {$pivotLabel} ";

        $returnValue['error'] = false;
        $returnValue['message'] = 'Ok';
        $returnValue['sql'] = $pivotQry;
        return $returnValue ;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM