2014-10-06 2 views
3

Я только что открыл эту удивительно полезную функцию MySQL GROUP_CONCAT. Он кажется настолько полезным и чрезмерно упрощающим для меня, что я действительно боюсь его использовать. В основном потому, что прошло довольно много времени с тех пор, как я начал заниматься веб-программированием, и я никогда его нигде не видел. Образец удивительного использования будет следующим:Причины не использовать GROUP_CONCAT?

Таблица clients содержит клиентов (вы не говорите ...) одну строку на одного клиента с уникальными идентификаторами.
Таблица currencies имеет 3 колонки client_id, currency и amount.

Теперь, если я хотел бы получить пользователь 15-х name от clients стола и его остатки, со «старым» методом массива перезапись я должен сделать используйте следующий SQL

SELECT id, name, currency, amount 
FROM clients LEFT JOIN currencies ON clients.id = client_id 
WHERE clients.id = 15 

Тогда в PHP I придется перебрать результирующего набора и сделать перезапись массив (который я действительно не большой поклонник, особенно в массивных наборов результатов), как

$result = array(); 
foreach($stmt->fetchAll() as $row){ 
    $result[$row['id']]['name'] = $row['name']; 
    $result[$row['id']]['currencies'][$row['currency']] = $row['amount']; 
} 

Однако с недавно обнаруженной функции я могу использовать это

SELECT id, name, GROUP_CONCAT(currency) as currencies GROUP_CONCAT(amount) as amounts 
FROM clients LEFT JOIN currencies ON clients.id = client_id 
WHERE clients.id = 15 
GROUP BY clients.id 

Затем на вещах уровня приложений настолько удивительные и очень

$results = $stmt->fetchAll(); 
foreach($results as $k => $v){ 
    $results[$k]['currencies'] = array_combine(explode(',', $v['currencies']), explode(',', $v['amounts'])); 
} 

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

EDIT:

Я хочу спросить, в конце концов, какие другие варианты, кроме массива перезапись, чтобы в конечном итоге с многомерного массива из результирующего набора данных MySQL, потому что если я выбрать 15 столбцов, это действительно большой боль в шее, чтобы написать этого зверя.

+1

это удобно, но это не универсально. Он имеет ограниченную длину в строке, которую он может вернуть, обычно по умолчанию 1024 символа. Если у вас есть «большой» набор данных, ваша упорядоченная строка может легко превышать 1024 символа, и она будет беззвучно усечена/повреждена. –

+1

Все это описано здесь http://stackoverflow.com/questions/276927/can-i-concatenate-multiple-mysql-rows-into-one-field/276949#276949 –

+1

Эта длина может быть настроена –

ответ

6
  • Использование GROUP_CONCAT() обычно вызывает логику group-by и создает временные таблицы, которые обычно являются большим негативным для производительности. Иногда вы можете добавить нужный индекс, чтобы избежать временной таблицы в запросе группы, но не в каждом случае.

  • Как указывает @MarcB, предел длины по умолчанию для строки с конкатенацией групп довольно короткий, и многие люди были смущены усеченными списками. Вы можете увеличить лимит с group_concat_max_len.

  • Разрыв строки в массив в PHP не предоставляется бесплатно. Просто потому, что вы можете сделать это в одном вызове функции в PHP, это не значит, что это лучшее для производительности. Я не сравнивал эту разницу, но сомневаюсь, что вы тоже.

  • GROUP_CONCAT() - это MySQLism. Он не поддерживается широко другими продуктами SQL. В некоторых случаях (например, SQLite) у них есть функция GROUP_CONCAT(), но она не работает точно так же, как и в MySQL, поэтому это может привести к запутывающим ошибкам, если вам необходимо поддерживать несколько RDBMS-back-end. Конечно, если вам не нужно беспокоиться о портировании, это не проблема.

  • Если вы хотите извлечь несколько столбцов из таблицы currencies, вам потребуются несколько выражений GROUP_CONCAT(). Являются ли списки гарантированными в том же порядке? То есть третье поле в одном списке соответствует третьему полю в следующем списке? Ответ - нет, если вы не укажете порядок с предложением ORDER BY внутри GROUP_CONCAT().

Я обычно благоприятствуют свой формат первого кода, использовать обычный набор результатов, и цикл по результатам, сохранение в новый массив индексируется идентификатором клиента, добавляя валюты в массив. Это простое решение, упрощает и упрощает SQL, и работает лучше, если у вас есть несколько столбцов для извлечения.

Я не пытаюсь сказать GROUP_CONCAT() это плохо! Это очень полезно во многих случаях. Но попытка сделать любое правило одного размера для всех (или избегать) любой функции или языка упрощается.

+0

То, что я пропустил в этом ответе, является объяснением, почему никогда не бывает веской причины даже для того, чтобы в первую очередь нуждаться в групповом конфликте. – wvdz

+0

Перезапись массива @popovitsj с большими наборами результатов и большим количеством выбранных столбцов неэффективна и боль к коду, не является ли это веской причиной? (Не говоря, что group_concat более эффективен, просто думает) –

+0

@popovitsj, см. Мой ответ на https://programmers.stackexchange.com/questions/90456/why-dont-relational-databases-support-returning-information-in- a-вложенный формат, включая обсуждение в комментариях. –

2

Самая большая проблема, которую я вижу с GROUP_CONCAT, заключается в том, что она очень специфична для MySql: если вы хотите портировать свой код для работы с любой другой платформой, вам придется переписать все запросы, которые используют GROUP_CONCAT. Например, ваш первый запрос намного более переносимый - вы, вероятно, можете запустить его против любого крупного механизма RDBMS, не меняя в нем ни одного символа.

Если вы в порядке с работой только с MySql (скажем, потому что вы пишете инструмент, предназначенный специально для MySql), запросы с GROUP_CONCAT, вероятно, будут быстрее, потому что РСУБД сделает больше работы для вас, сохраняя размер передачи данных.

+3

Порт моего кода? Человек мой код не будет работать, если моя температура в комнате изменится! lol ': D' –

Смежные вопросы