|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Существует такая проблема Есть две таблицы 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 Перебор звонков в курсоре - еще медленнее. Ести ли у кого идеи как это еще можно реализовать поменяв структуру базы и/или запросы? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2001, 15:45 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Если есть возможность, то менять нужно структуру базы, табличка Calls у Вас явно не укладывается даже в 1-ю НФ, поскольку поле DialedNumber содержит составные данные а именно - Код звонка и Номер Звонка. Пэтому и такие трудности с выборкой. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2001, 16:33 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Недообъяснял Я имел в виду то, что вам нужно как минимум разделить столбец DialedNumber на два, хотя подозреваю что вся схема данных непродумана и несоответствует предметной области. Если Ваша система сейчас только разрабатывается я бы посоветовал серьезно взяться за разработку схемы данных. Почитайте Дейта. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2001, 16:37 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Согласенс Genady. Добавлю еще что такая постановка не верна в принципе. Например, в Вашем примере был звонок 78123222222. Т.е. (7812)3222222. А как будет выглядеть номер звонка в этот же город с местным телефоном 2222222? (7812)2222222. А в Вашем представлении - 78122222222, что ничем не отличается от (781)22222222. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2001, 17:15 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Я так понимаю что номера приходят без разделения их на код города и собственно номер. В принципе можно их разделять при вставке. Но наверное не стоит, т.к. таблица меняется оперативно и тормозить тут нельзя. Можно таблицу 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... но это дело вкуса С приветом Сергей ... |
|||
:
Нравится:
Не нравится:
|
|||
14.03.2001, 17:30 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Сергей, вы правы - номера приходят с АТС в неразделенном виде. Генадий, Идея разделять номер на код+остаток была, но она не годится в силу того что для разных тарифных планов могут использоватся разные набор кодов, например, Набраны 781223456 -для клиента с планом N1 781223456 -для клиента с планом N2 В Плане 1 задан только код 7 -$0,2 В Плане 2 заданы коды 7812 - 0,10 78122 -0,05 То есть получаем что один и тот же номер должен разбится в одном случае как (7)81223456 а в другом как (78122)3456. таким образом мы не можем заранее сказать что номер состоит из кода и остатка не посмотрев на тарифный план. Дмитрий, не совсем понял ваш пример. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 15:26 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
>Идея разделять номер на код+остаток была, но она не годится в силу того что для разных тарифных планов могут использоватся >разные набор кодов, например Это не повод запихивать два атрибута в один, отношение многие ко многим никто не отменял Анализ предметной области при правильном определении сущностей и их атрибутов спасут "отцов русской демократии" Как я писал уже ранне нужно просто серьезно отнестись к проектированию схемы данных, начиная с концептуальной модели да помогут вам ER диаграммы ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 15:59 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
>>Это не повод запихивать два атрибута в один, отношение многие ко многим никто не отменял. В том-то все и дело, что это изначально один атрибут -номер "физически" набранный на телефоне. Задача в том и состоит чтобы наиболее эффективным способом разделить этот номер на два атрибута- "значащий код" на основе которого звонку ставится в соответствие тариф и "балласт" -остаток номера. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 16:54 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Может есть какие нибудь идеи по поводу модификации таблицы Rates? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 17:12 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Вобщем я тут посмотрел внимательно беру свои слова назад, правда не совсем, ошибка все таки у Вас есть, поскольку я не вижу связи 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. Вопрос: а вычисляемое поле сознательно храните? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 17:20 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Да, Вы правы нужно модифицировать Rates, поскольку номер есть номер, но код все равно хранить надо отдельно, вот только непонятно назначение поля RateID. Кстати хорошей практикой является натменование таблиц в единственном числе, поскольку каждая запись таблицы определяет один экземпляр конкретной сущности (логической или физической), проще потом будет разбираться в схеме, да и в построении помогает ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 17:26 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
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 - тогда да. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 17:39 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
По поводу единственного числа, не судите строго - я просто привел упрощенный пример, на самом деле все в единственном числе называется да и таблицы не из трех полей состоят (да и не две их там..). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 17:47 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Ууууу, как все запущено дядюшка Кодд учит нас убирать повторяющиеся группы из таблиц Табличка то Rates у вас в 1-й НФ, вы запихнули две сущности в одну, мой совет, тарифные планы и коды разделить надобно, всей постановки не знаю, но возможно, что код звонка нужно просто атрибутом запихнуть в Call, ну что бы сказать поточнее надо анализировать. Кстати почитайте Дейта, хотя бы до глав по нормальным формам, уделив внимание на аномалим обновления, вставки и удаления в различных формах - гарантирую Вы порадуетесь. кстати, мой запросик таки сработает правильно я предположил, что ключ у Вас составной, поэтому substr-ом его как бы ввел в табличку Calls, но мой совет остается в силе - Rates надо делить ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 18:10 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Читал я все это.Rates специально денормализована для ускорения работы. Когда идет UPDATE на 1000000 записей то тут не до нормальных форм. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2001, 21:02 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Кстати, запросик то сработает, но не гарантированно - зависит от того в каком порядке "Физически" были вставлены записи в таблицу 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 ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 09:23 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Ндааа..... денормализация позволяет ускорить select, а уж никак не update 8-[] Интересно как Вы себе это представляете? Подумайте сами, вместо обновления одной записи Вам приходится обновлять набор записей. Запрос щас проверять лень, потом посмотрю, но даже если не работает, ситуация лечится просто Вопрос: если у Вас в Rates составной PK, то почему FK у вас состоит из части PK????!!! ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 10:22 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Так я же SELECT и ускоряю - SELECT идет из денормализованной RATES для update таблицы Calls. >>Вопрос: если у Вас в Rates составной PK, то почему FK у вас состоит из части PK????!!! Непонял, почему части? ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 11:06 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
A запрос можно просто cut and paste сделать в Query analyser - только результаты SELECT'ов удалить и запустить. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 11:07 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
>Когда идет UPDATE на 1000000 записей то тут не до нормальных форм. Очепятка что ли? Насколько я понял отношение между Rates и Calls - один ко многим, соответственно составной PK Rates должен присутствовать как FK в Calls и проблем как не бывало ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 11:22 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Да в этом то задача и состоит чтобы определить какому PK в Rates соответствует запись в Calls. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 11:54 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
>Да в этом то задача и состоит чтобы определить какому PK в Rates соответствует запись в Calls. Уффф... Victor, если бы Вы внимательно читали литературу по реляционным базам, то Вы бы знали, что для этих целей используют связку PK -> FK и не придумывали бы себе проблем. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 12:06 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Действительно Уффф. Такое впечатление что мы с вами говорим на разных языках. Может я чего-то не улавливаю, но я не вижу каким образом ваши комментарии относительно определения ключей имеют отношение к моей задаче. Если можно, приведите конкретный пример. >>>>Когда идет 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 ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 12:31 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
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 ? Что об этом в книгах пишут? Как по другому таблицы организовать? Чиста канкретна можете написать? А критиковать-то и советовать книжки почитать - это просто. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 12:36 |
|
UPDATE по совпадению в подстроке
|
|||
---|---|---|---|
#18+
Да уж, действительно на разных языках Вот что я хотел сказать: Судя по тому, что вам нужно связать строки из Calls со строками из Rates, между этими таблицами существует отношение и это отношение - один ко многим. Первичный ключ Rates состоит из двйх полей - RateID, DestinationCode. Для того, чтобы организовать отношение Parent Child, нужно из парента передать в чилд первичный ключ в виде внешнего ключа, т. е. поля составляющие первичный ключ Rates должны присутствовать Calls, таким образом будет организовано однозначное соответствие. Уфф замаялся я совсем с Вами, по моему я объяснил достаточно подробно. Если непонятно я уже ничего сделать не могу, учите матчасть ... |
|||
:
Нравится:
Не нравится:
|
|||
16.03.2001, 12:46 |
|
|
start [/forum/topic.php?fid=46&msg=32003079&tid=1827173]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
29ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
others: | 264ms |
total: | 398ms |
0 / 0 |