Я использую jquery flot charts для представления моих данных. Вот пример JSFiddle, который я сделал, который показывает, как должны выглядеть JSONS для диаграммы.
Источник данных из хранимой процедуры MySql, которая имеет пример ниже:
Мне нужно представить на диаграмме, значения count
уложенные для разных innumber
по оси Y, значения name
по оси x и в другой таблице – значения для outnumber
. (в штабелированных барах).
– Серия данных должна соответствовать, поэтому конкретные ярлыки должны появляться против клиентов.
Вот PHP, который у меня есть до сих пор:
$query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)"); $customers = $query->result_array(); foreach ($customers as $customer) { if($customer['innumber'] != null){ $chartInbound['name'] = $customer['name']; $chartInbound['label'] = $customer['innumber']; $chartInbound['count'] = $customer['count']; $chartInbound['customerid'] = $customer['id']; array_push($out['chartInbound'], $chartInbound); } if($customer['outnumber'] != null){ $chartOutbound['name'] = $customer['name']; $chartOutbound['label'] = $customer['outnumber']; $chartOutbound['count'] = $customer['count']; $chartOutbound['customerid'] = $customer['id']; array_push($out['chartOutbound'], $chartOutbound); } }
Результат print_r($out['chartInbound']);
является:
Array ( [0] => Array ( [name] => 1st Online Solutions [label] => 01-02 [count] => 577 [customerid] => 129 ) [1] => Array ( [name] => Bookngo [label] => 01-02 [count] => 2 [customerid] => 95 ) [2] => Array ( [name] => Boutixury [label] => 07 [count] => 1 [customerid] => 14 ) [3] => Array ( [name] => Cruise Village [label] => 01-02 [count] => 16 [customerid] => 25 ) [4] => Array ( [name] => Cruise Village [label] => 00 [count] => 1 [customerid] => 25 ) [5] => Array ( [customer] => Cruise Village [label] => 07 [countInbound] => 16 [minsInbound] => 125 [customerid] => 25 ) ................... )
Вывод print_r(json_encode($out['chartInbound']));
является:
[ { "name": "1st Online Soultions" "label": "01-02", "count": "577", "customerid": "129" }, { "name": "Bookngo" "label": "01-020", "count": "2", "customerid": "129" }, { "name": "Boutixury" "label": "07", "count": "1", "customerid": "14" }, { "name": "Cruise Village" "label": "07", "count": "16", "customerid": "25" }, ................. ]
Но это не очень полезно.
В: Как я могу создать динамический JSON, показанный в приведенном выше jsfiddle, из данных запроса?
Просматривая данные с помощью цикла и newData
newTicks
массивы newData
и newTicks
для использования newTicks
:
var newData = []; var newLabels = []; // only used to get index since newData has objects in it var newTicks = []; for (var i = 0; i < dataFromServer.length; i++) { var datapoint = dataFromServer[i]; var tick = newTicks.indexOf(datapoint.name); if (tick == -1) { tick = newTicks.length; newTicks.push(datapoint.name); } var index = newLabels.indexOf(datapoint.label); if (index == -1) { index = newLabels.length; newLabels.push(datapoint.label); newDataPoint = { label: datapoint.label, data: [] }; newDataPoint.data[tick] = [tick, datapoint.count]; newData.push(newDataPoint); } else { newData[index].data[tick] = [tick, datapoint.count]; } } for (var i = 0; i < newTicks.length; i++) { newTicks[i] = [i, newTicks[i]]; } newLabels = null;
Мне также пришлось сменить генерацию всплывающей подсказки, поскольку ваш код работал только тогда, когда все типы данных были заполнены и отсортированы. Это также проще.
полная скрипка
Просто идея, я полагаю, вы используете группу в своей хранимой процедуре. Если вы можете изменить его и добавить WITH ROLLUP, в базе данных будет рассчитан счетчик … См. https://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html или поиск SO для предложения
Вы можете сделать это на стороне клиента (хотя в идеале это должно быть сделано на стороне сервера), используя что-то вроде:
var table = [ {name: 'a', label: 'l1', count: '15', customerid: '1'}, {name: 'a', label: 'l2', count: '1', customerid: '1'}, {name: 'a', label: 'l3', count: '7', customerid: '1'}, {name: 'b', label: 'l1', count: '3', customerid: '2'}, {name: 'b', label: 'l2', count: '9', customerid: '2'}, {name: 'b', label: 'l3', count: '2', customerid: '2'}, {name: 'c', label: 'l1', count: '1', customerid: '3'}, {name: 'c', label: 'l2', count: '7', customerid: '3'}, {name: 'a', label: 'l3', count: '5', customerid: '4'}, {name: 'a', label: 'l2', count: '6', customerid: '4'} ]; var customers = {}; var labels = {}; var i; for (i = 0; i < table.length; ++i) { customers[table[i].customerid] = table[i].name; labels[table[i].label] = labels[table[i].label] || []; labels[table[i].label].push([+table[i].customerid, +table[i].count]); } var chartData = []; var chartTicks = []; for (customer in customers) { if (customers.hasOwnProperty(customer)) { chartTicks.push([+customer, customers[customer]]); } } for (label in labels) { if (labels.hasOwnProperty(label)) { chartData.push({label: label, data: labels[label]}); } }
В нем учитываются разные клиенты (разные клиенты) с тем же именем (хотя Flot на самом деле не справляется с этим), а также клиенты с отсутствующими данными для некоторых ярлыков. Не следует слишком сильно перекладывать эту логику на PHP и делать это на стороне сервера.
EDIT: Хорошо, я не заметил, что это действует странно, когда есть метки «пробелы». Вот пересмотренный код:
var table = [ {name: 'a', label: 'l1', count: '15', customerid: '1'}, {name: 'a', label: 'l2', count: '1', customerid: '1'}, {name: 'a', label: 'l3', count: '7', customerid: '1'}, {name: 'b', label: 'l1', count: '3', customerid: '2'}, {name: 'b', label: 'l2', count: '9', customerid: '2'}, {name: 'b', label: 'l3', count: '2', customerid: '2'}, {name: 'c', label: 'l1', count: '1', customerid: '3'}, {name: 'c', label: 'l2', count: '7', customerid: '3'}, {name: 'a', label: 'l3', count: '5', customerid: '7'}, {name: 'a', label: 'l2', count: '6', customerid: '7'} ]; var customers = {}; var labels = {}; var chartData = []; var chartTicks = []; var i; var customerNo = 0; for (i = 0; i < table.length; ++i) { if(!customers.hasOwnProperty(table[i].customerid)) { customers[table[i].customerid] = table[i].name; chartTicks.push([customerNo, table[i].name]); customerNo++; } labels[table[i].label] = labels[table[i].label] || []; labels[table[i].label].push([customerNo - 1, +table[i].count]); } for (label in labels) { if (labels.hasOwnProperty(label)) { chartData.push({label: label, data: labels[label]}); } }
Идентификаторы меток указываются в том порядке, в котором они отображаются в таблице, поступающей с сервера. (Хотя он по-прежнему различает двух клиентов с тем же именем, но с разными идентификаторами клиентов)
Вам придется преобразовать структуры самостоятельно. Вы можете делать это на стороне сервера или на стороне клиента. В любом случае выполните результаты и постройте нужную структуру. Будьте осторожны, пытаясь закодировать ассоциативные массивы php в json и остерегаться поведения NUMERIC_CHECK.
Похоже, что ваши точки данных в chartTicks[i]
должны соответствовать порядку тиков в chartData[i].data
. Один из способов обеспечить такое совпадение – сортировать данные по имени в sql и сначала складывать результаты по клиенту, а второй – по php.
$query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)"); $customers = $query->result_array(); //should be sorted by name $results = array(); foreach ($customers as $customer) { $i = is_array($results[$customer['name']][$customer['innumber']]) ? count($results[$customer['name']][$customer['innumber']]) : 0; //stack data points by customer name first and label second $results[$customer['name']][$customer['innumber']][] = array($i,$customer['count']); } $chartData = array(); $chartTicks = array(); $i=0; foreach($results as $name => $labels) { $chartTicks[] = array($i++,$name); foreach($labels as $label => $data) { $chartData[] = array( 'label' => $label, 'data' => $data, ); } } print json_encode($chartData); print json_encode($chartTicks);
-во$query = $this->db->query("call GetAllCustomersV2($id, $year, $month, $day)"); $customers = $query->result_array(); //should be sorted by name $results = array(); foreach ($customers as $customer) { $i = is_array($results[$customer['name']][$customer['innumber']]) ? count($results[$customer['name']][$customer['innumber']]) : 0; //stack data points by customer name first and label second $results[$customer['name']][$customer['innumber']][] = array($i,$customer['count']); } $chartData = array(); $chartTicks = array(); $i=0; foreach($results as $name => $labels) { $chartTicks[] = array($i++,$name); foreach($labels as $label => $data) { $chartData[] = array( 'label' => $label, 'data' => $data, ); } } print json_encode($chartData); print json_encode($chartTicks);
Это кратчайший способ превратить вашу текущую структуру данных JSON в желаемый результат:
var reduced; var chartData = Object.keys(reduced = data.reduce(function(a, b) { if(a[b.label]) { a[b.label].push([a[b.label].length, parseInt(b.count, 10)]); } else { a[b.label] = [[0, parseInt(b.count, 10)]]; } return a; }, {})).map(function(key) { return { label: key, data: reduced[key] }; });
Сценарий: http://jsfiddle.net/rdkgbteq/1/
Вот то же самое в PHP, если вы хотите преобразовать данные на сервере:
$reduced = array_reduce($data, function($result, $current) { if(array_key_exists($current['label'], $result)) { array_push($result, [count($result[$current['label']]), $current['count']]); } else { $result[$current['label']] = [[0, $current['count']]]; } return $result; }, array()); $formatted = array_map(function($key) { return array( 'label' => $key, 'data' => $reduced[$key] ); }, array_keys($reduced)); echo json_encode($formatted);
Дайте мне знать, если вы хотите, чтобы я расширил то, что здесь происходит.