Сортировка с использованием UTF символов в MySQL или PHP?лучшие решения - PullRequest
5 голосов
/ 04 марта 2011

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

  • ¡Decirevilla!
  • Альгамбра
  • 123 pasitos
  • Африка
  • Arroz
  • Decir

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

  • 123 pasitos
  • Африка
  • Альгамбра
  • Арроз
  • ¡Decirevilla!
  • Decir

После всех исследований, которые я прочитал, я пришел к выводу, чтонет разумного способа добиться этого с помощью 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: Все это имеет смысл?Я на правильном пути?

Спасибо заранее за все ваши советы.Marco

Ответы [ 2 ]

1 голос
/ 04 марта 2011

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

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

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

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

  • 123 пасито
  • африки
  • Alhambra
  • аррос
  • decirevilla
  • decir

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

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

0 голосов
/ 04 марта 2011

Вопрос 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. Да.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...