powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите с запросом.
12 сообщений из 12, страница 1 из 1
Помогите с запросом.
    #32858809
andreeyka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть табличка для телефонии в иде

prefix | oper
-------------
7095 | 1
70951 | 2
7096 | 1
70962 | 2
70966 | 3

Далее ко мне приходит 70951234567
Мне нужно поймать максимальное совпадение поля prefix к пришедшему номеру. Вот думаю как сделать как все покрасивее :).
Записей может быть до нескольких десятков тысяч в таблице, запросов для начала до 5 в секунду, дальше и больше.
Щас наскору руку спрашиваю так
SELECT max(prefix) from routes where '70951234567' like prefix||'%'
ну это блин не красиво выглядит ), тем более что еще придеться еще кучу других вычислений в запросе делать.

Мож кто скажет как сделать этот запрос по красивее.
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32859754
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
на скорую руку возникла
приблизительно такая идея:

select * from routes
where
70951234567 between

prefix*10^(char_length('70951234567')-char_length(prefix))

and

(
prefix*10^(char_length('70951234567')-char_length(prefix))
+10^(char_length('70951234567')-char_length(prefix))-1
)

можно помудрить с этим, думаю это быстрее like будет, но походу выглядит еще более уродски :)

правда еще вопрос какого типа поле prefix?
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32859994
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Развивая:
т.к. between работает и с текстом (проверяю)
Код: plaintext
1.
2.
3.
4.
SELECT * FROM test
WHERE
   '12345678901' between name 
AND
name ||'9'
, то от 10^ххх можно уйти:
Код: plaintext
1.
2.
3.
4.
5.
6.
select * from routes 
where 
 70951234567  between
prefix
and 
prefix||'9')
ORDER BY prefix DESC LIMIT  1 
Однако не думаю, что это будет шибко шустрее Like (т.к. при поиске по LIKE _с начала строки_ нормальные СУБД юзают индекс, не с начала - не юзают).
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32860043
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
assabetween prefix and prefix||'9'ошибка: select '70959876543' between '7095' and '7095'||'9';
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32860047
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
'70951234567' like prefix||'%'

ужо очень сомневайсь про индекс... парент в лайке далеко не константа хоть и в начале.
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32860209
фффф
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если длина префиксов ограничена (как в примере - 4 и 5 символа), то можно построить несколько частичных индекса для каждой из длин. Но запрос тогда придется разбить на несколько частей, объединенных по UNION, чтобы частичные индексы использовались. Вроде такого:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
CREATE INDEX routes_prefix4 on routes(prefix) WHERE char_length(prefix)= 4 ;
CREATE INDEX routes_prefix5 on routes(prefix) WHERE char_length(prefix)= 5 ;

SELECT prefix, oper, char_length(prefix) as len
FROM routes
WHERE substring('70951234567' from  1  for  5 )=prefix
  and char_length(prefix)= 5 
UNION
SELECT prefix, oper, char_length(prefix) as len
FROM routes
WHERE substring('70951234567' from  1  for  4 )=prefix
  and char_length(prefix)= 4 
ORDER BY len DESC
LIMIT  1 ;
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32860482
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1/ LeXa NalBat assabetween prefix and prefix||'9'ошибка: select '70959876543' between '7095' and '7095'||'9';
правим:
select '70959876543' between '7095' and '7095'||'a';

2/ индекс и для between не пользуется (там выражения от prefix -> нужны ф-ные индексы)

3/ быстрее всего по фффф, но можно как то так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
CREATE OR REPLACE FUNCTION public.test_pref(text)
  RETURNS SETOF text AS
'
SELECT substring($1 from 1 for 1)
UNION ALL
SELECT substring($1 from 1 for 2)
UNION ALL
SELECT substring($1 from 1 for 3)
UNION ALL
SELECT substring($1 from 1 for 4)
UNION ALL
SELECT substring($1 from 1 for 5)
UNION ALL
SELECT substring($1 from 1 for 6)
UNION 
SELECT substring($1 from 1 for 7);'
  LANGUAGE 'sql' STABLE;

/*----------------*/
SELECT test_pref('7095');

Суммарное время выполнения запроса: 31  ms.
Время получения данных: 0  ms.
получено строк:  4 
а уж на нее вязаться джойном
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32860514
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в тако случае проще сделать простой индекс по prefix,и телефон урезать до max(char_length(prefix)) символов слева и сравнивать простым =
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32860588
assa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wbearв тако случае проще сделать простой индекс по prefix,и телефон урезать до max(char_length(prefix)) символов слева и сравнивать простым =
и окажется, что обрезанный телефон не имеет тчоного =, а надо обрезать истчо одну (2,3) букк-фу. Т.ч. надо открошить все варианты длин.

Если не нравится джон, то открошить в строку stroka через запятую , и делать через
EXECUTE 'SELECT ... WHERE prefix IN('||stroka||')' (чё плохо тем, что может быть только в ф-ии)
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32860809
wbear
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
точно , сорру, это я что то неподумавши ляпнул .
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32866817
andreeyka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В приципе все балее менее ясно. Завтра на работе погоняю по базе посмотрю что и как.
А еще есть такая идея.
Длина префикса может быть от 1 знака до 11. поле тип varchar(16)
Те всю 7 выбрать на 1 оператора, а 70951234567 на 2.
У меня такая мысль.
Так как я все делаю в ф-ии.
То беру и с конца начинаю отрезать по одному знаки и по "=" искать простым селектом, пока мне не вернуться данные.

Правда запросов будет куча но они все будут без возврата данных. Тк чаще префикс от 2-5 знаков, те 11 - (2-5)= 6-9 запросов селект. но с простым условием.
...
Рейтинг: 0 / 0
Помогите с запросом.
    #32867132
andreeyka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блин тестирую пока везде одинаковая производительность. Все запросы у меня по 20 мсек. Мож руки дойдут напишу прогу которая сгенерит файл с кучей запросов (тыщ 10). и погонять базу.

ЗЫ. Вот здесь сошлись как у меня сначала.
/topic/116302&hl=

Более того автор то топика сидит от меня в 2 метрах.
Вот так то все сразу в форумы кидаються
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите с запросом.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]