Мне было интересно, если бы SQL-запрос мог возвращать данные, используя некоторые записи в SQL. Извините, если это не явно (не на английском, я думаю, вы поняли), так что давайте посмотрим на пример:
$req = $bdd->prepare('SELECT u.u_id, u.u_name, um.um_id, um.um_name, um.um_value
FROM users as u
LEFT JOIN users_metas as um ON um.um_uid = u.u_id');
$prepare->execute();
$datas = $prepare->fetchAll();
Итак, я собираюсь $datas
массив как
$datas = array(
0 =>
u_id => 1
u_name => name
um_id => 1
um_name => meta_name1
um_value => meta_value1
1 =>
u_id => 1
u_name => name
um_id => 2
um_name => meta_name2
um_value => meta_value2
...
);
Что бы я хотел это что-то вроде:
$datas = array(
0 =>
u_id => 1
u_name => name
meta_name1 => meta_value1
meta_name2 => meta_value2
1 =>
u_id => an other user
...
);
У меня уже есть это после того, как я вручную позабочусь о $datas
, но мне было интересно, смогу ли я достичь этой презентации без обработки, только с помощью SQL?
Я надеюсь, что вы, ребята, поймете меня, я сделаю все возможное, чтобы объяснить, если у вас есть вопросы.
С уважением.
MySQL решение
Преобразование табличного выражения в таблицу путем преобразования уникальных значений из одного столбца в таблице в несколько столбцов в выходных данных называется сводной. В отличие от некоторых других СУБД, MySQL не имеет PIVOT
или же CROSSTAB
функция, так что вы не можете написать один размер подходит для всех решений этой проблемы.
Если вы знаете все возможные значения um_name
заранее вы можете эмулировать это поведение, используя агрегатные функции.
SELECT u.u_id, u.u_name,
MAX(CASE WHEN um_name = 'meta_name1' THEN um_value END) meta_name1,
MAX(CASE WHEN um_name = 'meta_name2' THEN um_value END) meta_name2
FROM users as u
LEFT JOIN users_metas as um ON um.um_uid = u.u_id
GROUP BY u.u_id, u.u_name;
Недостатком этого решения является то, что вы должны продолжать добавлять MAX(CASE WHEN um_name = '...' THEN um_value END)
столбцы в запросе для каждого возможного значения um_name
,
Теоретически вы можете сгенерировать этот запрос в PHP, выбрав все um_name
сначала значения, но это не сделает ваш код проще или быстрее, так что нет особого смысла.
PHP решение
В качестве альтернативы, это всего несколько строк PHP для преобразования вашего текущего вывода из fetchAll()
в формате, который вы хотите.
$out = [];
array_walk($datas, function($v) use(&$out) {
$out[$v["u_id"]] = (isset($out[$v["u_id"]]) ? $out[$v["u_id"]] : [])
+ ["u_id" => $v["u_id"],
"u_name" => $v["u_name"],
$v["um_name"] => $v["um_value"]];
});
$out = array_values($out);
Это не устанавливает ключи, если запись не существует в users_metas
стол, так что вам нужно проверить с isset
до доступа к определенному значению, если оно присутствует не для всех пользователей.
Других решений пока нет …