База данных кодов телефонов

MaxiStyle

Новичок
База данных кодов телефонов

Задача:
Необходимо определить регион к которому принадлежит телефонный номер, для этого существует список кодов телефона.
Напрмер: телефон 9243000000
В списке код телефона: 92430 => Хабаровский край.

Для этого организовал структуру:
//справочник регионов
CREATE TABLE `region` (
`rid` int(11) NOT NULL
`region` varchar(100) NOT NULL
PRIMARY KEY (`rid`)
);
//справочник кодов
CREATE TABLE `cods` (
`cod` int(11) NOT NULL,
`rid` int(11) NOT NULL,
PRIMARY KEY (`cod`)
);


Скрипт получает номер телефона и перебирает его в базе:
"SELECT rid FROM cods WHERE
cod LIKE LEFT('".$nomer."',8) OR
cod LIKE LEFT('".$nomer."',7) OR
cod LIKE LEFT('".$nomer."',6) OR
cod LIKE LEFT('".$nomer."',5) OR
cod LIKE LEFT('".$nomer."',4) OR
cod LIKE LEFT('".$nomer."',3)
LIMIT 1"

Основная проблема в том, что код телефона переменной длянаы и неизвестно какая часть телефона является кодом.
Используемое мною решение справляется с задачей. Однако порой необходимо определить регион у 10000 номеров.
Есть ли более рациональное решение такой задачи?
 

MaxiStyle

Новичок
WP
Это шутка? Ну хотя бы потому что именно mysql сейчас стоит не сервере.
Предлагаете сразу Oracle?
 

Gas

может по одной?
MaxiStyle
зачем используется like, когда нужно сравнить 2 числа?

Предлагаете сразу Oracle?
откуда такие фантазии? для этой задачи оптимальным есть хранение копии этой таблицы в памяти и извлечение по hash-индексу. Можешь хоть memcache, хоть mysql memory engine использовать. Только если иногда нужно определять коды 10000 номеров, то это скорее всего не web-приложение и нет конкурентности запросов, следовательно таких заморочек и не нужно.
 

fast2111

Новичок
Определить попадание номера в интервал [a, b] и работать только с числами без Like.

Здесь именно так и делают
http://payment.cyberplat.com/distr/terminal/db_numcapacity.7z
(архив со списком интервалов номеров по операторам мобильной связи)

Если я не ошибаюсь :)
 

Alexandre

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

nirex

Новичок
MaxiStyle
сделай отдельное поле для кода телефона, с экономишь время на поиске и нервы людей, которые юзают твой "лайковый" запрос )

-~{}~ 16.05.08 15:09:

и индекс не забудь повесить на это поле, будет летать )))
 

MaxiStyle

Новичок
Gas
Хранить копию таблицы в памяти? Там 10000 кодов телефонов...

fast2111
Предлагаете изметить формат таблицы кодами? Т.е.
Вместо

id региона | код
--------------+------
2 | 92430
2 | 92440

Сделать:
id региона | код1 | код2
--------------+----------------+---------------
2 | 9243000000|9243099999
2 | 9244000000|9244099999

Так? И что через beteween будет быстрее, за счет отсутствия LEFT?

Alexandre
С LIKE я конечно погорячился...
Но проблема в том, что первые 3 цифры не дают инфу о городе и даже о областе. Операторы так все усложнили, что для определения области надо от 3 до 8 первых цифр!!!

nirex
Так в таблице и так отдельное поле с PRIMARY KEY.


Спасибо за советы. Так все же как лучше: грузить таблицу кодов в память, переделать таблицу кодов для использования between или:

"SELECT rid FROM cods WHERE cod = LEFT('".$nomer."',8) LIMIT 1"
если не нашли...
"SELECT rid FROM cods WHERE cod = LEFT('".$nomer."',7) LIMIT 1"
если не нашли...
"SELECT rid FROM cods WHERE cod = LEFT('".$nomer."',6) LIMIT 1"
если не нашли...
"SELECT rid FROM cods WHERE cod = LEFT('".$nomer."',5) LIMIT 1"
и т.д...
 

Wicked

Новичок
id региона | код1 | код2
--------------+----------------+---------------
2 | 9243000000|9243099999
2 | 9244000000|9244099999
+
select * from ... where код1 <= '".$nomer."' and '".$nomer."' <= код2;
или его более оптимизированный аналог:
select * from (select * from ... where код1 <= '".$nomer."' order by код1 asc limit 1) as t where '".$nomer."' <= t.код2;
 

MaxiStyle

Новичок
Wicked
Спасибо!

-~{}~ 19.05.08 17:16:

Wicked
Там только не ASC, а DESC
А так, прирост скорости в 2,5 раза.
 

Alexandre

PHPПенсионер
Но проблема в том, что первые 3 цифры не дают инфу о городе и даже о областе. Операторы так все усложнили, что для определения области надо от 3 до 8 первых цифр!!!
что не дает?
код:
49653 - Пушкино
49646 - Раменское
49633 - Голицино
...

область Московская, не Магаданская и не Мурманская.

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

Например 841 - Пенза (8412) и область 841x
Камчатка 415хх

а не иной регион ....
 

MaxiStyle

Новичок
Alexandre
Вы меня немного не поняли.

90118 - Московская область
901461 - Московская область
901645 - Алтайский край
901641 - Иркутская область

Первые 3 цифры не есть код региона. У сотовых операторов, которым приходится покупать диапазона номеров, нет четкого разграничения по городам и областям, более того по сотовому номеру нельзя точно сказать в каком городе он зарегестрирован.
Если вытащить телефоны с кодом 901, то вылезет 1/5 всей базы кодов.

По экспериментам решение от Wicked самое быстрое, 1 сек 10000 номеров.
 
Сверху