Сортировка с использованием символов utf в mysql или php? лучшие решения


Используя MySQL, я выбираю список песен на испанском языке, которые я хотел бы отсортировать. Вот список имен, возвращаемых запросом:

  • ¡Дециревилья!
  • Альгамбра
  • 123 пасито
  • Африка
  • Арроз
  • Децир

Отсортированный список должен выглядеть следующим образом:

  • 123 пасито
  • Африка
  • Альгамбра
  • Арроз
  • ¡Дециревилья!
  • Децир

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

Вопрос 1: Является ли это разумным выводом?

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

function normalize($a, $b) {
  if ($a == $b) {
     return 0;
  }

  return ($a < $b) ? -1 : 1;
}


$tracks = array();

while ($row = $result->fetch_assoc()) {
    $tracks[] = $row;
}

usort($tracks, 'normalize');

Вопрос 2: Это лучший способ добиться пользовательской сортировки?

Вот где я упираюсь в стену:

Вопрос 3: Я понятия не имею, как создать функцию нормализации для сортировки имен в соответствии с моими потребностями. Как мне игнорировать определенные символы (¡, ?, ', !, ¿) и как мне заменить другие символы естественным эквивалентом (Á -> A, É -> E и т. Д.) Я верю что, игнорируя определенные символы и заменяя другие, я могу добиться сортировки, которую ищу...

Вопрос 4: Все это имеет смысл? На правильном ли я пути?

Заранее спасибо за все ваши советы. Марко

Author: mu is too short, 2011-03-04

2 answers

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

Выполнение искаженной сортировки на стороне клиента (т.Е. в PHP, а не в базе данных) будет не так быстро, как в базе данных. Этот подход также с треском провалится, как только вам придется добавить предложения LIMIT и OFFSET в свой запрос. Я не уверен, что обычай параметры сортировки делают правильные вещи для MAX() аналогичных функций, но выполнение искаженных параметров сортировки в PHP, безусловно, не будет, если вы не хотите просмотреть всю таблицу, отсортировать ее, а затем захватить только одну запись.

Итак, я бы рассмотрел возможность выполнения сортировки за пределами базы данных в качестве последнего средства.

Другой вариант, если вы не хотите создавать свои собственные параметры сортировки, - это создать искусственный столбец в вашей таблице, который выполняет правильную сортировку. Вы могли бы использовать функцию normalize() в PHP-land (что-то вроде Джейкоба было бы разумной отправной точкой) и сохранить результат в базе данных в виде столбца, называемого, скажем, sortable_title; тогда ORDER BY sortable_title сделает свое дело. Вам нужна функция normalize() PHP, которая создавала бы такой список (без знаков препинания, все в нижнем регистре, без акцентов, ...):

  • 123 пасито
  • африка
  • альгамбра
  • арроз
  • дециревилла
  • децир

Так что простая сортировка в формате ASCII будет правильной. Конечно, вы бы необходимо инициализировать sortable_title при выполнении вставок и восстанавливать его во время обновлений, но это должно быть довольно просто, если ваш код правильно инкапсулирован.

Вопрос 4: Я думаю, что не соглашусь с Джейкобом и скажу, что вы идете в неправильном направлении, удаляя параметры сортировки из базы данных. Я не говорю, что вы полностью сбились с пути, но вам лучше позволить MySQL обрабатывать сортировку, даже если в конечном итоге вы можете оказать ему некоторую помощь с чем-то вроде sortable_title взлом, описанный выше.

 1
Author: mu is too short, 2011-03-04 06:02:56

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

Вопрос 3. Возможно, стоит преобразовать строку в ее эквивалент ASCII с помощью iconv. Который может конвертировать UTF-8 в ASCII и, используя транслит, он будет соответствовать символу, который нельзя напрямую преобразовать во что-то похожее на него.

Т.е. Á -> A, É ->E и т. Д.

Как только он будет преобразован, вы сможете удалить символы, которые вы не хотите сортировать с помощью preg_replace или str_replace.

Вот пример функции сравнения, которую вы могли бы использовать.

function normalize_string($string) {
    $ascii = iconv("utf-8","ascii//TRANSLIT", $string);
    return str_replace(array('!', "'", '?'), '', $ascii);

    // or

    return preg_replace('/[!\'?]/', '', $ascii);

    // or depending on how much you do want to replace... \W => any "non-word" character

    return preg_replace('/\W/', '', $ascii);
}

function custom_str_cmp($a, $b) {
    return strcmp(normalize_string($a), normalize_string($b));
}

usort($tracks, 'custom_str_cmp');

Вопрос 4. Да.

 0
Author: Jacob, 2011-03-04 04:47:39