Помогите с выборкой уникальных данных

Kostyab

Новичок
Помогите с выборкой уникальных данных

Привет всем!
Есть база данных, одно из полей содержит город. Например, 100 человек из СПб, 150 из Москвы, 6 из Новгорода.
Задача: создать <select>, который будет выглядеть так:

Санкт-Петербург
Москва
Новгород

Я могу сделать так, чтобы <select> состоял из 100 полей СПб, 150 Москвы и так далее. Я пробовал использовать функцию array_unique() но ничего не вышло.

Я делаю так:
echo "<select name=\"city\">";
$query="SELECT city
FROM people
ORDER BY city";
$result=mysql_query($query);
$unik=(array_unique(mysql_fetch_array($result));
foreach($unik as $x)
{
echo"<option value=$x[city]>$x[city] ";
}
echo "</select>"

Но ничего не работает. Спасибо всем заранее! Пока.
 

.des.

Поставил пиво кому надо ;-)
DISTINCT(city)
и array_unique() не понадобится
 

Kostyab

Новичок
Вот это оперативность...! А ларчик просто открывался!
Спасибо!
 

Crazy

Developer
Кстати, а что быстрее работает: "select distict(...)" или "select ... group by ..."?
 

Nime

Guest
Для group by ведь еще нужны ф-и аггрегирования, а с ними, по идее, должно быть медленнее, чем при простой выборке.

Сугубо имхо :)
 

Crazy

Developer
Я, собственно, почему спросил: если индекса по этому полю нет, то в любом случае будет полное сканирование таблицы. Если индекс есть, то в обоих случаях можно провести полное сканирование индекса. Т.е. с точки зрения реализации обе реализации эквивалентны. Но я вполне допускаю, что есть нюансы. Может быть, кто-то экспериментировал?
 

Nime

Guest
Я не экспериментировал, но ведь в случае с group by помимо полного сканирования проводятся дополнительные расчёты, а это даёт основания полагать, что потребуется больше времени на исполнение. Или ошибка в цепочке? :)

Если тебя интересовали именно практические результаты, а не размышления на тему, то сорри :)
 

Crazy

Developer
В данном случае никаких рассчетов не проводится. :)

Будет время -- обязательно проверю.
 

Nime

Guest
Бррр, это же мискл... никогда не понимал какой смысл в group by без ф-й аггрегирования, а он поддерживает.

Так или иначе запрос distinct у меня выполнился за 0.16 сек, а с group by за 49.15 сек. Около 150 тысяч записей в таблице, а уникальных записей искомого поля около 700.
Разница была слишком очевидна и дальше продолжать не стал :)
 

.des.

Поставил пиво кому надо ;-)
Nime странно.. А можно спросить как ты тестировал?
вот у меня структура таблицы следующая.

CREATE TABLE dgtest (
id int(10) unsigned NOT NULL auto_increment,
name char(25) NOT NULL default '',
uq_field int(11) NOT NULL default '0',
note char(250) NOT NULL default '',
PRIMARY KEY (id),
KEY name (name(10))
) TYPE=MyISAM
В таблице 360900 записей
PHP:
Field_name  Min_value  Max_value  Min_length  Max_length
id             1        360900       1           6 
name           Ю        ЪЯМНЦН       1           20
uq_field -2146175631 2146048243      7           11
note        -------  ---------      248         249

PHP:
Тип       Использование 
данные  100MБ 
индекс     5MБ
PHP:
SELECT DISTINCT(name) FROM dgtest
выполняется в среднем 5-6 секунд.

PHP:
SELECT name FROM dgtest GROUP BY 1
выполняется в среднем 4-6 секунд.

PHP:
SELECT name,count(name) FROM dgtest GROUP BY 1
выполняется в среднем 4-6 секунд.

mysql version 4.0.0-alpha
OS Windows XP Pro
P2 400Mhz 256 Mb
 

Nime

Guest
Хм. Странно. Неужто я попал на момент когда какой-то обсчёт загрузил сервер и заблокировал таблицы? Я делал тоже самое только не group by 1, а group by field_name
Всё остальное аналогично по сути... я позже еще раз проверю (сейчас не под рукой таблица, а хочу проверить именно на ней), однако, скорее всего именно попал на неподходящий момент, так как на относительно небольшой таблице на собственном компе дает нормальные результаты... я еще отпостюсь :)
 

.des.

Поставил пиво кому надо ;-)
ах да важный момент из 360000 тысяч записей 2405 уникальных (name)
 

tony2001

TeaM PHPClub
>Господа, а что говорит explain?
вот и я это хотел спросить.
сначала explain, а потом уже тесты.
 

.des.

Поставил пиво кому надо ;-)
PHP:
mysql> explain select distinct(name) from dgtest;
+--------+------+---------------+------+---------+------+--------+-----------------+
| table  | type | possible_keys | key  | key_len | ref  | rows   | Extra           |
+--------+------+---------------+------+---------+------+--------+-----------------+
| dgtest | ALL  | NULL          | NULL |    NULL | NULL | 360900 | Using temporary |
+--------+------+---------------+------+---------+------+--------+-----------------+
1 row in set (0.01 sec)

mysql> explain select name from dgtest group by 1;
+--------+------+---------------+------+---------+------+--------+-----------------+
| table  | type | possible_keys | key  | key_len | ref  | rows   | Extra           |
+--------+------+---------------+------+---------+------+--------+-----------------+
| dgtest | ALL  | NULL          | NULL |    NULL | NULL | 360900 | Using temporary |
+--------+------+---------------+------+---------+------+--------+-----------------+
1 row in set (0.00 sec)
 

.des.

Поставил пиво кому надо ;-)
Сделал индекс name(25)
PHP:
mysql> explain select name from dgtest group by 1;
+--------+-------+---------------+------+---------+------+--------+-------------+
| table  | type  | possible_keys | key  | key_len | ref  | rows   | Extra       |
+--------+-------+---------------+------+---------+------+--------+-------------+
| dgtest | index | NULL          | name |      25 | NULL | 360900 | Using index |
+--------+-------+---------------+------+---------+------+--------+-------------+
1 row in set (0.01 sec)

mysql> explain select distinct(name) from dgtest;
+--------+-------+---------------+------+---------+------+--------+-------------+
| table  | type  | possible_keys | key  | key_len | ref  | rows   | Extra       |
+--------+-------+---------------+------+---------+------+--------+-------------+
| dgtest | index | NULL          | name |      25 | NULL | 360900 | Using index |
+--------+-------+---------------+------+---------+------+--------+-------------+
1 row in set (0.02 sec)
GROUP BY в среднем на 1 секунду быстрее.
[Поправка - не быстрее.. не сбросил кэш таблицы.] оба запроса одинаковое время показывают. И не удивительно судя по explain
Общая скорость выборки ускорилась примерно на секунду.
 
Сверху