Group_Concat
Начиная с версии 4.1 в mySql существует функция Group_Concat. Временами она бывает весьма полезна, может кому-нибудь пригодится.
Вот выдержка из PHPInside (#19' 2007)
Формат записи прост:
GROUP_CONCAT (выражение)
Данная функция возвращает строку результата с объединенными значениями из группы, не
равными NULL. Где это может пригодиться?
Для примера рассмотрим получение массива в PHP без введения циклов внутри самого PHP-кода.
CREATE TABLE services (
id INT UNSIGNED NOT NULL,
client_id INT UNSIGNED NOT NULL,
KEY (id));
INSERT INTO services
VALUES (1,1),(1,2),(3,5),(3,6),(3,7);
SELECT id,client_id FROM services WHERE id = 3;
+—-+———–+
| id | client_id |
+—-+———–+
| 3 | 5 |
| 3 | 6 |
| 3 | 7 |
+—-+———–+
SELECT id,GROUP_CONCAT(client_id) FROM services WHERE id = 3 GROUP BY id;
+—-+————————-+
| id | GROUP_CONCAT(client_id) |
+—-+————————-+
| 3 | 5,6,7 |
+—-+————————-+
CODE:
<?php
$res=$mysqli->query(”SELECT id,client_id FROM services WHERE id = 3″);
while ($row = $res->fetch_array(MYSQLI_ASSOC)) {
$result[] = $row['client_id'];
}
$res->free();
?>
PHP Inside'19 >> В фокусе >> Использование GROUP_CONCAT в GROUP BY
И в ситуации с group_concat:
<?php
$res=$mysqli->query(”SELECT id,GROUP_CONCAT(client_id) as clients FROM
services WHERE id = 3 GROUP BY id”);
$row = $res->fetch_array(MYSQLI_ASSOC))
$result = explode(',', $row['clients']; // $row['clients'] contains
string 5,6,7
$res->free();
?>
Второе решение будет более быстрым, так как мы убираем лишние проходы по циклу средствами
PHP и передаем эту задачу на более быстрый уровень MySQL.
Иногда бывает полезно использовать результат конкатенации в выражении IN:
<?php
$res=$mysqli->query(”SELECT id,GROUP_CONCAT(client_id) as clients FROM
services WHERE id = 3 GROUP BY id”);
$row = $res->fetch_array(MYSQLI_ASSOC))
$result = $row['clients']; // $row['clients'] contains string 5,6,7
$res->free();
$resclients=$mysqli->query(”SELECT id,client_name FROM clients WHERE
id = IN ($result)”);
// handle $resclients
?>
Конечно, последний пример может быть реализован и с помощью JOIN, но иногда нам нужны
временные ID в коде, к примеру в случаях выполнения запроса на другом сервере.
И последнее: иногда вы можете добавлять ORDER BY NULL после GROUP BY, чтобы избежать
ненужной сортировки с filesort.
Я ее использую когда есть дерево, хранящееся в базе в формате id, parent_id и его надо вытащить целиком начиная с рута (т.е. с parent_id=0 или null). Как правило это построение древовидного меню. Выглядит это примерно вот так:
select parent_id, group_concat(id) as childs from tree Group By parent_id;
В результате получаем табличку вида:
parent_id | childs
0 | 1,2
1 | 3, 5
2 | 4, 8
и т.д.
Т.е. для каждого узла получаем id его прямых потомков через разделитель. По сути структуру, которая полностью описывает дерево.
Применимо далеко не всегда, например пока не придумал, как получать по отдельности ветки дерева (подозреваю что подобным способом никак) но когда надо выдернуть целиком дерево очень удобно - один запрос вместо рекурсии.
Комментариев нет
Комментариев нет.
Извините, комментирование на данный момент закрыто.