从foreach

时间:2015-05-07 21:50:04

标签: javascript php mysql json flot

我正在使用jquery flot charts来表示我的数据。这是我所做的示例JSFiddle,它显示了图表所需的JSONS应该如何。

数据源来自具有以下输出示例的MySql存储过程:

enter image description here

我需要在图表中表示,y轴上不同count的{​​{1}}值,x轴上的innumber值以及另一个图表中的值{ name的值。 (在堆积的条形图中)。

- 数据系列应该匹配,因此特定标签应该针对客户显示。

这是我到目前为止的PHP:

outnumber

$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']));

但这不是很有帮助。

问:如何从查询数据中创建上述jsfiddle中显示的动态JSON?

6 个答案:

答案 0 :(得分:10)

使用循环遍历数据并构建要使用的fl newDatanewTicks数组:

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;

我还必须更改您的工具提示生成,因为您的代码仅在完成和排序的所有数据集时才有效。它现在也更简单。

complete fiddle

答案 1 :(得分:4)

你可以在客户端(虽然理想情况下应该在服务器端完成),通过使用类似的东西:

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中,而是在服务器端进行。

修改 好吧,当有labelID“gap”时,我没有注意到它的行为很奇怪。这是修改后的代码:

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]});
    }
}

标签ID按照它们出现在来自服务器的表中的顺序给出。 (虽然它仍然区分具有相同名称但不同客户ID的两个客户)

答案 2 :(得分:4)

只是一个想法,我想你在你的存储过程中使用了一个组。如果您可以修改它并添加WITH ROLLUP,数据库将为您计算计数...请参阅https://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html或搜索SO以获取建议

答案 3 :(得分:2)

你将不得不自己改造结构。您可以执行此服务器端或客户端。无论哪种情况,都要运行结果并构建所需的结构。 小心尝试在json中编码php关联数组,并注意NUMERIC_CHECK的行为。

答案 4 :(得分:2)

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);

答案 5 :(得分:2)

这是将当前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);

如果您希望我扩展这里发生的事情,请告诉我。