powered by simpleCommunicator - 2.0.41     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / UPDATE по совпадению в подстроке
25 сообщений из 61, страница 1 из 3
UPDATE по совпадению в подстроке
    #32003028
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Существует такая проблема

Есть две таблицы

Calls (DialedNumber,Duration,RateId,Cost) - телефонные звонки (50000-1млн записей)

Например
70957777777 60 5 NULL
78122222222 60 6 NULL
78123222222 60 6 NULL

Rates (RateId,DestinationCode,Rate) - тарифы (>200000 записей)
Например
5 7095 0,5
6 7095 0,5
6 7812 0,5 - действителен для всех звонков вида 7812xxx кроме 78122
6 78122 0,1

таким образом звонки должны тарифицироваться согласно тарифу для кода который
наиболее совпадает с набранным номером т.е. 7812222222 будет по тарифу 0,1 ,а
7812322222 по тарифц 0,5.

Собственоо вопрос - как это лучше всего реализовать на SQL Server?

Пробовал три способа
1. Цикл по длинне кода в таблице rates - оказался самый быстрый
DECLARE @codelen tinyint
SELECT @codelen=10
WHILE @codelen>0
BEGIN
UPDATE calls
SET cost=duration*Rate
WHERE substring(DialedNumber,1,datalength(DestinationCode))=DestinationCode
and datalength(destinationcode)=@codelen
and calls.rateid=rates.rateid
and cost is null
SELECT @codelen=@codelen-1
END
2. Один запрос - очень медленно
UPDATE calls
SET cost=duration*rates.rate
from rates
WHERE rates.Destinationcode=(select max(destinationcode) from rates r1 where dialednumber like code+'%' and rates.rateid=r1.rateid)
and rates.rateid=calls.rateid

3 Перебор звонков в курсоре - еще медленнее.

Ести ли у кого идеи как это еще можно реализовать поменяв структуру базы и/или запросы?
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003033
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если есть возможность, то менять нужно структуру базы, табличка Calls у Вас явно не укладывается даже в 1-ю НФ, поскольку поле DialedNumber содержит составные данные а именно - Код звонка и Номер Звонка. Пэтому и такие трудности с выборкой.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003034
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Недообъяснял

Я имел в виду то, что вам нужно как минимум разделить столбец DialedNumber на два, хотя подозреваю что вся схема данных непродумана и несоответствует предметной области. Если Ваша система сейчас только разрабатывается я бы посоветовал серьезно взяться за разработку схемы данных. Почитайте Дейта.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003036
dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Согласенс Genady. Добавлю еще что такая постановка не верна в принципе. Например, в Вашем примере был звонок 78123222222. Т.е. (7812)3222222. А как будет выглядеть номер звонка в этот же город с местным телефоном 2222222? (7812)2222222. А в Вашем представлении - 78122222222, что ничем не отличается от (781)22222222.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003037
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я так понимаю что номера приходят без разделения их на код города и собственно номер. В принципе можно их разделять при вставке. Но наверное не стоит, т.к. таблица меняется оперативно и тормозить тут нельзя.

Можно таблицу Rates записывать примерно так:
5 7095% 0,5
6 7095% 0,5
6 7812[^2]% 0,5
6 78122% 0,1
и тогда всё будет делаться одним запросом ... WHERE DialedNumber like DestinationCode ...
правда замучиешься вести таблицу Rates

Я бы остановился на твоём первом варианте, только написал бы WHERE DialedNumber like DestinationCode+'%' and datalength(DestinationCode)=@codelen... но это дело вкуса

С приветом Сергей
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003064
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей,
вы правы - номера приходят с АТС в неразделенном виде.

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

Набраны
781223456 -для клиента с планом N1
781223456 -для клиента с планом N2

В Плане 1 задан только
код 7 -$0,2
В Плане 2 заданы коды
7812 - 0,10
78122 -0,05
То есть получаем что один и тот же номер должен разбится в одном случае как (7)81223456 а в другом как (78122)3456.
таким образом мы не можем заранее сказать что номер состоит из кода и остатка не посмотрев на тарифный план.

Дмитрий,
не совсем понял ваш пример.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003068
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Идея разделять номер на код+остаток была, но она не годится в силу того что для разных тарифных планов могут использоватся >разные набор кодов, например

Это не повод запихивать два атрибута в один, отношение многие ко многим никто не отменял

Анализ предметной области при правильном определении сущностей и их атрибутов спасут "отцов русской демократии"
Как я писал уже ранне нужно просто серьезно отнестись к проектированию схемы данных, начиная с концептуальной модели

да помогут вам ER диаграммы
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003070
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>>Это не повод запихивать два атрибута в один, отношение многие ко многим никто не отменял.
В том-то все и дело, что это изначально один атрибут -номер "физически" набранный на телефоне.
Задача в том и состоит чтобы наиболее эффективным способом разделить этот номер на два атрибута- "значащий код" на основе которого звонку ставится в соответствие тариф и "балласт" -остаток номера.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003072
victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Может есть какие нибудь идеи по поводу модификации таблицы Rates?
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003073
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вобщем я тут посмотрел внимательно
беру свои слова назад, правда не совсем, ошибка все таки у Вас есть, поскольку я не вижу связи Rates c Calls если бы RateID был PK, то все можно было бы сделать просто:

update Calls set Calls.Cost = Calls.Duration * Rates.Rate from Calls, Rates where Calls.RateID = Rates.RateID

В Вашем случае можно обойтись, но не советую, таким запросом:

update Calls set Calls.Cost = Calls.Duration * Rates.Rate from Calls, Rates
where Calls.RateID = Rates.RateID and Rates.DestinationCode = substring(Calls.DialingNumber, 1, len(Rates.DestinationCode))

Вобщем совет - определитесь с ключиками

P.S. Вопрос: а вычисляемое поле сознательно храните?
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003074
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, Вы правы нужно модифицировать Rates, поскольку номер есть номер, но код все равно хранить надо отдельно, вот только непонятно назначение поля RateID.

Кстати хорошей практикой является натменование таблиц в единственном числе, поскольку каждая запись таблицы определяет один экземпляр конкретной сущности (логической или физической), проще потом будет разбираться в схеме, да и в построении помогает
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003075
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
RateID это номер тарифной таблицы которую необходимо использовать для тарификации того или иного звонка. PK для таблицы Rates это (rate_id,destinationcode):
RateId,DestinationCode,Rate
--начало первой таблицы
1 7095 0,2
1 7096 0,1
1 7812 0,3
1 78122 0,2
1 781222 0,3
--начало второй таблицы
2 7095 0,01
2 7096 0,02
2 7812 0,03
-- начало третей таблицы
3 7 0,20


Увы,ваш запрос будет работать в случае таблиц 1 и 3, но в случае 2 несработает:
набранному номеру 78122222 будут соответствовать три позиции таблицы -где гарантия что UPDATE будет использовать именоо 781222 ?
Если бы можно было сделать
UPDATE....
ORDER BY DATALENGTH(781222) DESC - тогда да.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003076
victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
По поводу единственного числа,
не судите строго - я просто привел упрощенный пример, на самом деле все в единственном числе называется да и таблицы не из трех полей состоят (да и не две их там..).
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003079
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ууууу, как все запущено
дядюшка Кодд учит нас убирать повторяющиеся группы из таблиц

Табличка то Rates у вас в 1-й НФ, вы запихнули две сущности в одну, мой совет, тарифные планы и коды разделить надобно, всей постановки не знаю, но возможно, что код звонка нужно просто атрибутом запихнуть в Call, ну что бы сказать поточнее надо анализировать. Кстати почитайте Дейта, хотя бы до глав по нормальным формам, уделив внимание на аномалим обновления, вставки и удаления в различных формах - гарантирую Вы порадуетесь.


кстати, мой запросик таки сработает правильно я предположил, что ключ у Вас составной, поэтому substr-ом его как бы ввел в табличку Calls, но мой совет остается в силе - Rates надо делить
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003088
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Читал я все это.Rates специально денормализована для ускорения работы. Когда идет UPDATE на 1000000 записей то тут не до нормальных форм.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003097
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кстати, запросик то сработает, но не гарантированно - зависит от того в каком порядке "Физически" были вставлены записи в таблицу Rates.

Пример:
CREATE TABLE Calls (DialedNumber varchar(14),Duration int,RateId int,Cost money)
CREATE TABLE Rates (RateId int,DestinationCode varchar(14),Rate money)

INSERT INTO Calls (DialedNumber,Duration,RateId)VALUES ('7095x',60,5)
INSERT INTO Calls (DialedNumber,Duration,RateId)VALUES ('78122x',60,6)
INSERT INTO Calls (DialedNumber,Duration,RateId)VALUES ('78123x',60,6)
INSERT INTO RATES (RateId,DestinationCode,Rate) VALUES (5,'7095',0.5)
--Вставляем сначала короткий код а затем длинный
INSERT INTO RATES (RateId,DestinationCode,Rate) VALUES (6,'7812',1)
INSERT INTO RATES (RateId,DestinationCode,Rate) VALUES (6,'78122',2)

update Calls set Calls.Cost = Calls.Duration * Rates.Rate from Calls, Rates
where Calls.RateID = Rates.RateID and Rates.DestinationCode = substring(Calls.DialedNumber, 1, len(Rates.DestinationCode))

select * from calls
--Получаем результат:
DialedNumber Duration RateId Cost
-------------- ----------- ----------- ---------------------
7095x 60 5 30.0000
78122x 60 6 120.0000
78123x 60 6 60.0000

truncate table rates

INSERT INTO RATES (RateId,DestinationCode,Rate) VALUES (5,'7095',0.5)
-- а теперь вставляем сначала длинный код а затем короткий
INSERT INTO RATES (RateId,DestinationCode,Rate) VALUES (6,'78122',2)
INSERT INTO RATES (RateId,DestinationCode,Rate) VALUES (6,'7812',1)

update Calls set Calls.Cost = Calls.Duration * Rates.Rate from Calls, Rates
where Calls.RateID = Rates.RateID and Rates.DestinationCode = substring(Calls.DialedNumber, 1, len(Rates.DestinationCode))

select * from calls
DialedNumber Duration RateId Cost
-------------- ----------- ----------- ---------------------
7095x 60 5 30.0000
78122x 60 6 60.0000
78123x 60 6 60.0000
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003101
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ндааа..... денормализация позволяет ускорить select, а уж никак не update 8-[]
Интересно как Вы себе это представляете? Подумайте сами, вместо обновления одной записи Вам приходится обновлять набор записей.

Запрос щас проверять лень, потом посмотрю, но даже если не работает, ситуация лечится просто
Вопрос: если у Вас в Rates составной PK, то почему FK у вас состоит из части PK????!!!
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003107
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так я же SELECT и ускоряю - SELECT идет из денормализованной RATES для update таблицы Calls.
>>Вопрос: если у Вас в Rates составной PK, то почему FK у вас состоит из части PK????!!!

Непонял, почему части?
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003108
victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
A запрос можно просто cut and paste сделать в Query analyser - только результаты SELECT'ов удалить и запустить.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003110
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Когда идет UPDATE на 1000000 записей то тут не до нормальных форм.
Очепятка что ли?

Насколько я понял отношение между Rates и Calls - один ко многим, соответственно составной PK Rates должен присутствовать как FK в Calls и проблем как не бывало
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003112
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да в этом то задача и состоит чтобы определить какому PK в Rates соответствует запись в Calls.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003115
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Да в этом то задача и состоит чтобы определить какому PK в Rates соответствует запись в Calls.

Уффф... Victor, если бы Вы внимательно читали литературу по реляционным базам, то Вы бы знали, что для этих целей используют связку PK -> FK и не придумывали бы себе проблем.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003118
Victor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Действительно Уффф. Такое впечатление что мы с вами говорим на разных языках.

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

>>>>Когда идет UPDATE на 1000000 записей то тут не до нормальных форм.
>> Очепятка что ли?
Имел в виду что

UPDATE calls
SET rate=.....
FROM rates --вот он SELECT который я имел в виду
WHERE ....
будет быстрее чем

UPDATE calls
SET rate=
FROM rates_normalized inner join codes on..
inner join ...
inner join ...
inner join ...
WHERE
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003120
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Genady

ну есть две таблица
id tel
-- ----
1 111
2 222
3 233

code rate
---- ----
1 4
2 5
23 6

как получить табличку

tel rate
--- ----
111 4
222 5
233 6

?

Что об этом в книгах пишут? Как по другому таблицы организовать?
Чиста канкретна можете написать?
А критиковать-то и советовать книжки почитать - это просто.
...
Рейтинг: 0 / 0
UPDATE по совпадению в подстроке
    #32003121
Genady
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да уж, действительно на разных языках

Вот что я хотел сказать:

Судя по тому, что вам нужно связать строки из Calls со строками из Rates, между этими таблицами существует отношение и это отношение - один ко многим. Первичный ключ Rates состоит из двйх полей - RateID, DestinationCode. Для того, чтобы организовать отношение Parent Child, нужно из парента передать в чилд первичный ключ в виде внешнего ключа, т. е. поля составляющие первичный ключ Rates должны присутствовать Calls, таким образом будет организовано однозначное соответствие.

Уфф замаялся я совсем с Вами, по моему я объяснил достаточно подробно. Если непонятно я уже ничего сделать не могу, учите матчасть
...
Рейтинг: 0 / 0
25 сообщений из 61, страница 1 из 3
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / UPDATE по совпадению в подстроке
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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