Welcome to PHPClub
Переходим на PHP 5.3.3! Ищем хорошего PHP-разработчика Москва,
офис ~90-150К
Боишься нашего дизайна?
поиск:
   
 Начало | Настройки | Расширенный поиск | РегистрацияПосмотреть новые сообщения 
  
PHP Club форумы: > PHP и базы данных > PHP & Mysql > Изм енить сортировку в MySQL
 

Автор
Тема ОТВЕТИТЬ
Кошакевич
Новичок

На форуме с: May 2008
Cообщений: 2
Город:
Изм енить сортировку в MySQL

Стандартная функция сортировки выдает сначала цифры, потом английский по алфавиту, затем русский по алфавиту.
Требуется чтобы сначала выдавался русский, потом английский, потом цифры.

Можно ли это сделать одним запросом без привлечения доп средств? Как сделать несколько запросов или сортировку уже в php я представляю, но система должна работать под большой нагрузкой, потому я считаю, что тратить системные ресурсы на эту бадягу излишне.

В базе примерно 500-600 записей. Из них с цифрами 10, англ 20-30. Вывод постраничный по 10 на стр.
PHP5. Версия сервера MySQL: 4.1.22

Old Post 26.05.08 10:59 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
zerkms
TDD infected

На форуме с: Jan 2004
Cообщений: 4929
Город: Komsomolsk-na-Amure, Russia

CASE тебе в руки

__________________
tvfёdor - оперативно уведомляет о раздачах rutracker

Old Post 26.05.08 11:00 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
Кошакевич
Новичок

На форуме с: May 2008
Cообщений: 2
Город:

Подскажите, пожалуйста, как именно можно воспользоваться CASE?
*покурил мануалы*
Что-то в голову вообще не лезет...

Old Post 26.05.08 11:17 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
zerkms
TDD infected

На форуме с: Jan 2004
Cообщений: 4929
Город: Komsomolsk-na-Amure, Russia

hint1:

ORDER BY
CASE
WHEN первая буква английская THEN 1
WHEN первый знак - цифра THEN 2
ELSE 0
END,
`field`

:-)


__________________
tvfёdor - оперативно уведомляет о раздачах rutracker

Old Post 26.05.08 11:28 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
JD
Новичок

На форуме с: Feb 2005
Cообщений: 36
Город: Kharkov, Ukraine
Re: Изм енить сортировку в MySQL

 
В базе примерно 500-600 записей. Из них с цифрами 10, англ 20-30.


Если в дальнейшем записи будут распределяться примерно таким же образом, записей будет много и сервер дейсвительно работает под большой нагрузкой, то, возможно, стоит пересмотреть порядок выражений, выполняемых в условии
 
ORDER BY CASE WHEN первая буква английская THEN 1 WHEN первый знак - цифра THEN 2 ELSE 0 END, `field`


и изменить его в соответсвии с количесвом записей, которые под них попадают. т.е. в данном случае:
CASE
WHEN первая буква русская THEN 0
WHEN первая буква англ THEN 1
ELSE 2
END

т.к. в таком случае вероятность выполнения второго выражение меньше

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

Old Post 01.06.08 17:30 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
Gas
может по одной?

На форуме с: Jul 2002
Cообщений: 2106
Город: dp.ua

 
с тремя запросами в юнионе


при таких исходных данных, теоритически он должен быть медленне чем order by case

Если б меня беспокоила скорость, сделал бы отдельное поле с "порядком для сортировки"+нужный индекс. Но на 500 записей, наверное, этот того не стоит.

Old Post 01.06.08 18:24 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
HraKK
Демиург

На форуме с: Dec 2005
Cообщений: 2681
Город: Киев

а гугл молчит? В MySQL можно настраивать самому порядки сортировки.

Old Post 01.06.08 18:39 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
Gas
может по одной?

На форуме с: Jul 2002
Cообщений: 2106
Город: dp.ua

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

[deleted]

Отредактировано Gas 01.06.08 в 21:14

Old Post 01.06.08 21:03 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
fixxxer
Старожил PHPCluba

На форуме с: May 2003
Cообщений: 3976
Город: Moscow, Russia

заведи дополнительное поле (скажем order_type), которое
0 если первая буква - русская
1 - латинская
2 - цифра
и делай order by ( order_type, твоя строка )

а если уж надо не только по первому символу это правило соблюдать, тогда ой, делай свой collation

Old Post 01.06.08 21:06 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
zerkms
TDD infected

На форуме с: Jan 2004
Cообщений: 4929
Город: Komsomolsk-na-Amure, Russia

 
Если в дальнейшем записи будут распределяться примерно таким же образом, записей будет много и сервер дейсвительно работает под большой нагрузкой, то, возможно, стоит пересмотреть порядок выражений, выполняемых в условии


кхе-кхе... :-) чот слабо верится. аргументация?


__________________
tvfёdor - оперативно уведомляет о раздачах rutracker

Old Post 01.06.08 21:59 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
JD
Новичок

На форуме с: Feb 2005
Cообщений: 36
Город: Kharkov, Ukraine

 
Автор оригинала: zerkms
кхе-кхе... :-) чот слабо верится. аргументация?


аргумент: если записей с русскими буквами >90% (как указал топикстартер), то в таком же количестве слуаев будет выполняться только выражение из первого CASE'а с проверкой на русскую букву. выражение во вротом CASE'е будет выполнятся только в том случае, если первый не вернет true. Если надо, могу привести пример.

Old Post 02.06.08 11:02 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
zerkms
TDD infected

На форуме с: Jan 2004
Cообщений: 4929
Город: Komsomolsk-na-Amure, Russia

JD
супер. а теперь продемонстрируй алгоритм определения "что буква русская" в конструкции WHEN первая буква русская THEN 0
м?


__________________
tvfёdor - оперативно уведомляет о раздачах rutracker

Old Post 02.06.08 11:59 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
JD
Новичок

На форуме с: Feb 2005
Cообщений: 36
Город: Kharkov, Ukraine

 
Автор оригинала: zerkms
супер. а теперь продемонстрируй алгоритм определения "что буква русская" в конструкции WHEN первая буква русская THEN 0
м?


первое что пришло в голову: `column` REGEXP '^[а-я]'
на MySQL: 5.0.51a работает:
SQL:


SELECT 'фыв'
REGEXP '^[а-я]' AS rus, 'asd'
REGEXP '^[а-я]' AS eng, '123'
REGEXP '^[а-я]' AS num

code:
+-----+-----+-----+ | rus | eng | num | +-----+-----+-----+ | 1 | 0 | 0 | +-----+-----+-----+

возможно, есть и другие способы...

Old Post 02.06.08 12:41 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
zerkms
TDD infected

На форуме с: Jan 2004
Cообщений: 4929
Город: Komsomolsk-na-Amure, Russia

 
на MySQL: 5.0.51a работает:


1. учёл ли ты юникод? а букву "ё" :-)
2. для английского быстрее будет ORD(`field`) BETWEEN ... делать

а теперь отправь это в BENCHMARK() и сравни производительность


__________________
tvfёdor - оперативно уведомляет о раздачах rutracker

Old Post 02.06.08 12:44 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
JD
Новичок

На форуме с: Feb 2005
Cообщений: 36
Город: Kharkov, Ukraine

 
1. учёл ли ты юникод? а букву "ё" :-)


с юникодом проблем быть не должно. а буква "ё" прохоидт нормально
 
2. для английского быстрее будет ORD(`field`) BETWEEN ... делать
а теперь отправь это в BENCHMARK() и сравни производительность


это ты уже перешел на оптимизацию самих выражений ;-)
я не отрицал наличие других вариантов выражений. бесспорно, ORD() BETWEEEN будет работать быстрее, чем REGEXP.

вот, что у меня получилось:
REGEXP - не особо быстр, зато выглядит красивее и понятнее, чем следующие за ним примеры :-)
BENCHMARK(1000000, ('фыв' REGEXP '^[а-я]'))
1 row in set (0.23 sec)

Вот эти выражения будут выполняться всегда, когда будет попадаться русская буква (а по условию это >90% случаем)
проверки на англ. букву в верхнем и нижнем регистре, и на цифру.
BENCHMARK(1000000, ( (ORD('фыв') BETWEEN 65 AND 90) OR (ORD('фыв') BETWEEN 97 AND 122) OR (ORD('фыв') BETWEEN 48 AND 57) ))
1 row in set (0.24 sec)
или
BENCHMARK(1000000, ( (ORD(UPPER('фыв')) BETWEEN 65 AND 90) OR (ORD('фыв') BETWEEN 48 AND 57) ));
1 row in set (0.25 sec)

Вот такие выражения необходими для распознавания русской буквы
Проверка на руск букву в верхнем регистре (тут не забыта любимая буква zerkmsа ;-) - "ё") (больше ничего не забыл?)
BENCHMARK(1000000, ( (ORD(UPPER('фыв')) BETWEEN 53392 AND 53423) OR (ORD(UPPER('фыв')) = 53377) ) );
1 row in set (0.28 sec)

А если учесть, что, как я понял, BENCHMARK() выполняет все выражения, а в CASE...WHEN... выполняется минимально необходимое количество (т.е. в данном случае, если буква русская, но не Ё, то ORD(UPPER('фыв')) = 53377) выполняться не будет) и буква "ё" встречается очень редко, то для теста выражение можно упростить до:
BENCHMARK(1000000, (ORD(UPPER('фыв')) BETWEEN 53392 AND 53423) );
1 row in set (0.12 sec)

т.е. при установке в первом CASE'е условия на проверку русск.буквы, то на 1000000(!) записей получаем
выигрыш примерно в (0.24 - 0.12) = 0,12 sec с вероятностью >0.9 отсюда, средний выигрыш (0,12 * 0,9) = 0,108 sec

Это конечно мелочь и её можно списать на погрешность, но все же Поправьте, если я что-то напутал или неправильно понял идею с ORD() BETWEEN

-~{}~ 02.06.08 19:57:

Ещё можно поиграться с вынесением ORD(UPPER('фыв')) "за скобки". тогда просто получим выигрыш в количестве BETWEEN'ов

Old Post 02.06.08 17:53 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
zerkms
TDD infected

На форуме с: Jan 2004
Cообщений: 4929
Город: Komsomolsk-na-Amure, Russia

 
т.е. при установке в первом CASE'е условия на проверку русск.буквы, то на 1000000(!) записей получаем
выигрыш примерно в (0.24 - 0.12) = 0,12 sec с вероятностью >0.9


с какой стати? в предложенном мной варианте - проверяется, что буква английская или цифра. так что в худшем случае необходимо сравнивать время нахождения "буква латинская" + "цифра" vs время нахождения "буква русская"
 
Проверка на руск букву в верхнем регистре (тут не забыта любимая буква zerkmsа ;-) - "ё") (больше ничего не забыл?)
BENCHMARK(1000000, ( (ORD(UPPER('фыв')) BETWEEN 53392 AND 53423) OR (ORD(UPPER('фыв')) = 53377) ) );


code:
mysql> SELECT ORD(UPPER('а')); +-----------------+ | ORD(UPPER('а')) | +-----------------+ | 160 | +-----------------+ 1 row in set (0.00 sec)


а если так? ещё диапазоны добавь и переизмерь заново :-)
+ верни ё
 
буква "ё" встречается очень редко, то для теста выражение можно упростить до


отлично просто :-) сделай тогда сразу WHEN RAND() < 0.9, упрости. давай-давай, все нюансы учитывай, и ё, и ещё один диапазон кириллических знаков в ascii :-)


__________________
tvfёdor - оперативно уведомляет о раздачах rutracker
Отредактировано zerkms 02.06.08 в 22:12
Old Post 02.06.08 22:07 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
JD
Новичок

На форуме с: Feb 2005
Cообщений: 36
Город: Kharkov, Ukraine

 
с какой стати? в предложенном мной варианте - проверяется, что буква английская или цифра. так что в худшем случае необходимо сравнивать время нахождения "буква латинская" + "цифра" vs время нахождения "буква русская"


Именно это я и сравнивал. смотри, 2й и 3й BENCHMARK() VS 5й(упрощенный)

 
а если так? ещё диапазоны добавь и переизмерь заново :-)


По-идее, мы должны знать, в какой кодировке храним данные. Проверять по нескольким диапазонам из разных кодировок кажется неправильным.

 
+ верни ё

отлично просто :-) сделай тогда сразу WHEN RAND() < 0.9, упрости. давай-давай, все нюансы учитывай, и ё, и ещё один диапазон кириллических знаков в ascii :-)


Не надо впадать в крайности. Почему я убрал Ё я объяснял. И это не только потому, что она имеет маленькую частоту вхождения, а потому, как BENCHMARK() выполняет выражения.

Вот, Кошакевич уже, наверно, и забыл о своей проблеме, а мы тут с тобой спорим
Предлагаю сделать выводы и закончить
Вывод: вариант zerkmsа достаточно прост для понимания, быстр и не зависит от кодировки данных, но если учесть набор входных данных и немного извратиться, то можно получить небольшой вигрыш в скорости. Что важнее - зависит от каждого конкретного случая. В случае топикстартера, заморачиваться не стоит, но иметь ввиду, что есть и другие варианты, это хорошо.

Old Post 03.06.08 10:04 URL сообщения | инфо об авторе | жалоба | IP: Записан | редактировать | ОТВЕТИТЬ и ЦИТИРОВАТЬ
Время GMT. Текущее время 23:11. Подписаться на Тему | Версия для Печати
 

PHP Club форумы: > PHP и базы данных > PHP & Mysql > Изм енить сортировку в MySQL
 
Оценить:
 
 
 
 

 © 1997-2010 PHPClubTeam      

Powered by vBulletin Copyright © 2000-2010 Jelsoft Enterprises Limited.