Как создать json из наборов результатов mysqli_multi_query?

Я пытаюсь отобразить данные для начальной загрузки (4 столбца), используя php и ajax из mysqli_multi_query().

Мне не удалось заставить второй запрос работать с UNION или INNER JOIN. Я не программист, и мне почти удалось получить правильный результат, но по какой-то причине первый запрос возвращает «нулевое» значение.

Как я могу это изменить?

Вот пример журнала и мой код:

Уведомление PHP: Неопределенное смещение: 2 в строке 26 Уведомление PHP: Неопределенное смещение: 3 в строке 27 {"sEcho":1,"iTotalRecords":1,"iTotalDisplayRecords":1,"aaData":{"CommonInverterData":[{ «Дата»: null, «Создано»: null, «Экспорт»: «0,9921563111569116», «Импорт»: «1,8864974578334937»}

/* Database connection start */ 
include ('db.php');

$conn = mysqli_connect($hn, $un, $pw, $db) or die("Connection failed: " . mysqli_connect_error());

/* Database connection end */

$sql = "SELECT m.`date`, `day_energy`
        FROM `CommonInverterData`
        JOIN ( SELECT `date`, MAX(`time`) 'maxtime'
        FROM `CommonInverterData`
        GROUP BY `date`) m
        ON m.maxtime = `CommonInverterData`.`time`
        AND m.`date` = `CommonInverterData`.`date`;";

$sql .= "SELECT ABS(SUM((CASE WHEN `P_Grid`<0 THEN `P_Grid` ELSE 0 END) / 60000 )) as 'Export', SUM((CASE WHEN `P_Grid`>=0 THEN `P_Grid` ELSE 0 END) / 60000 ) as 'Import' FROM `PowerFlowRealtimeData` GROUP BY `date`;";

if (mysqli_multi_query($conn, $sql) or die(mysqli_error($conn))) {
    do {
        if ($result=mysqli_store_result($conn)) {
            $data = array();
            while( $rows = mysqli_fetch_row($result) ) {
                $data[] = array(
                    'Date' => $rows[2],
                    'Generated' => $rows[3],
                    'Export' => $rows[0],
                    'Import' => $rows[1],
                );
            } mysqli_free_result($result);
        }
    } while (mysqli_next_result($conn));
}
mysqli_close($conn);

$return = array(
    "sEcho" => 1,
    "iTotalRecords" => count($data),
    "iTotalDisplayRecords" => count($data),
    "aaData"=>$data);

echo json_encode($return);

person whismerhill    schedule 11.08.2017    source источник


Ответы (2)


Не путайте с mysqli_multi_query().

Запустите один запрос, соберите результаты в массив.
Запустите другой запрос, соберите результаты в массив.
Объедините результаты в один простой цикл.
ПРОБЛЕМА РЕШЕНА. Доступны простейшие инструменты.

Принимая во внимание, что наиболее разумным решением было бы использование фактического JOIN. Для Wish вы должны были задать вопрос SQL.

person Your Common Sense    schedule 11.08.2017

  1. Вы не проверяете mysqli_more_results().

  2. Вы пытаетесь получить доступ к 4 элементам в каждом наборе результатов, несмотря на то, что в каждом запросе предлагается только два элемента.

Я смешал ваш фрагмент с обобщенным блоком кода, который я создал некоторое время назад, чтобы помочь людям понять и отладить mysqli_multi_query(). Если после реализации этого все еще что-то не так, этот блок кода должен помочь вам изолировать причину.

$sql=["SELECT m.`date`, `day_energy`
        FROM `CommonInverterData`
        JOIN ( SELECT `date`, MAX(`time`) 'maxtime'
        FROM `CommonInverterData`
        GROUP BY `date`) m
        ON m.maxtime = `CommonInverterData`.`time`
        AND m.`date` = `CommonInverterData`.`date`",
      "SELECT ABS(SUM((CASE WHEN `P_Grid`<0 THEN `P_Grid` ELSE 0 END) / 60000 )) as 'Export',
        SUM((CASE WHEN `P_Grid`>=0 THEN `P_Grid` ELSE 0 END) / 60000 ) as 'Import'
        FROM `PowerFlowRealtimeData` GROUP BY `date`"
    ];

if(mysqli_multi_query($conn,implode(';',$sql))){
    do{
        // echo "<br><br>",key($sql),": ",current($sql);  // display key:value @ pointer
        if($result=mysqli_store_result($conn)){   // if a result set
            while($rows=mysqli_fetch_row($result)){
                // echo "<br>Cols: {$rows[0]}, {$rows[1]}";
                if(key($sql)===0){  (first query)
                    $tmp1[]=['Date'=>$rows[0],'Generated'=>$rows[1]];
                }else{  // key($sql)===1 (second query)
                    $tmp2[]=['Export'=>$rows[0],'Import'=>$rows[1]];
                }
            }
            mysqli_free_result($result);
        }
        // echo "<br>Rows = ",mysqli_affected_rows($conn); // acts like num_rows on SELECTs
    } while(next($sql) && mysqli_more_results($conn) && mysqli_next_result($conn));
}
if($mysqli_error=mysqli_error($conn)){
    echo "<br><br>",key($sql),": ",current($sql),"Syntax Error:<br>$mysqli_error";  // display array pointer key:value
}
mysqli_close($conn);

$data=array_replace_recursive($tmp1,$tmp2);  // blend the temporary arrays together
$return = array(
    "sEcho" => 1,
    "iTotalRecords" => count($data),
    "iTotalDisplayRecords" => count($data),
    "aaData"=>$data);

echo json_encode($return);

Правда в том, что mysqli_multi_query() не лучшая практика для этого случая. Если бы это была моя задача/проект, я бы попытался объединить запросы в один вызов (и полностью избегать вызова mysqli_multi_query()).

Вот ссылка, где я советую, что можно сделать с запросом UNION: https://stackoverflow.com/a/34758622/2943403 Если вы пойдете по этому пути, просто помните, что вы все равно будете создавать 2 столбца в строке (а не 4 столбца).

Как предполагает YourCommonSense, JOIN будет лучшей практикой, поскольку вы сможете создать 4 столбца в строке и упростить обработку набора результатов. Чтобы повторить YCS, это заслуживает нового вопроса с отдельными/дополнительными сведениями о таблицах вашей базы данных и желаемом результате. Если вы хотите получить качественный ответ о том, как написать запрос, обязательно включите sqlfiddle всех задействованных таблиц и объясните связи между таблицами.

person mickmackusa    schedule 11.08.2017
comment
Как вы думаете, почему использование множественных запросов имеет смысл в этом контексте? - person Your Common Sense; 11.08.2017
comment
@YourCommonSense Не знаю, но я не собираюсь принуждать ОП. Я посоветовал использовать альтернативный метод. Я недостаточно знаю (или не удосужился вникнуть) о структурах данных и запросах OP, чтобы предлагать конкретную альтернативу. - person mickmackusa; 11.08.2017
comment
Привет, микмакуса, и спасибо за твой сценарий. Ваш код работает, возвращая 4 столбца, но только для 1 строки, то есть сегодняшней даты, где до сих пор должно быть 12 строк по дате. - person whismerhill; 11.08.2017
comment
Мне удалось получить результат с помощью LEFT JOIN, возвращающегося к моему php-скрипту с помощью одного запроса. Спасибо всем. - person whismerhill; 11.08.2017