Правильный порядок в подцепке

Программирование на Атлантисе (VIP, FCOM, ARD), FastReport

Модераторы: m0p3e, edward_K, Модераторы

Nick
Местный житель
Сообщения: 331
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Белгород

Правильный порядок в подцепке

Сообщение Nick »

Как правильно объяснить то, что запрос:

Select
KatSopr.NSopr, KatSopr.DSopr,
SpSopr.Npp, SpSopr.KolFact, SpSopr.Price,
KatMc.Name
Where
((
101 /== KatSopr.VidSopr
and KatSopr.Nrec /== SpSopr.cSopr
and SpSopr.cMcUsl /== KatMc.Nrec
));

корректно выводит список приходных накладных с их спецификациями, а если в подцепке в последней строке поменять местами правую и левую часть: and KatMc.Nrec /== SpSopr.cMcUsl - то ничего в результат не попадает вообще.
Как понять правильно? В подцепке ведь слева стоит корневая таблица, а справа та, которая к ней цепляется (указывает на нее ссылкой)? или все-равно кто где?
Т.е. во второй строке правило соблюдено, а в третьей все наоборот.
Константы обязательно слева еще вроде как.
Где почитать?
edward_K
Заслуженный деятель интернет-сообщества
Сообщения: 5187
Зарегистрирован: 29 мар 2005, 17:49
Откуда: SPB galaxy spb

Re: Правильный порядок в подцепке

Сообщение edward_K »

1. при выборе получается декартово произведение записей в katsopr и katmc.
2.логичней тогда и другие строки переписать
101 == Spsopr.vidsopr and
1 == spsopr.prmc and
katmc.nrec == spsopr.cmcusl and
spsopr.csopr == katsopr.nrec
Nick
Местный житель
Сообщения: 331
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Белгород

Re: Правильный порядок в подцепке

Сообщение Nick »

Честно говоря, я не понял причем здесь декартово произведение записей - если не трудно - поясните пожалуйста.

А вот прочитал:
"...Конструкция Where позволяет не только накладывать ограничения на результат выборки, но и связывать таблицы. Необходимость связывать таблицы может понадобиться при извлечении данных сразу из нескольких таблиц. Связывание двух таблиц называется подцепкой.
Каждая подцепка устанавливает соответствие между отдельным полем подчиненной таблицы и полем родительской таблицы. Подцепка косвенным образом определяет индекс, который подбирается базой данных.
Для определения связи между полями родительской и подчиненной таблиц применяются специальные наборы символов:
==, /==, >>=, <<=, >>, <<

Слева от условия связи задаются выражения, которые могут содержать поле родительской таблицы и константы, а справа - поле подчиненной таблицы и атрибуты.
Реляционные связи могут быть двух типов - жесткие и мягкие.
При мягкой подцепке отсутствующие в подчиненной таблице записи заполняются значениеми по умолчанию. При жесткой подцепке записи родительской таблицы, для которых не были найдены записи в таблице-потомке, в выборку не попадают.

Еще я понял, что подцепка - это то, что заключено в скобки (( и )) и выполняется она на сервере, в отличие от фильтрации: того, что за этими скобками - выполняется на клиенте.

Таким образом:
KatMc.Nrec /== SpSopr.cMcUsl
более верная запись в подцепке, чем
SpSopr.cMcUsl /== KatMc.Nrec

Так как SpSopr - подчиненная таблица для KatMc - ведь спецификация накладной ссылается на МЦ, но работоспособный именно второй вариант ???
Nick
Местный житель
Сообщения: 331
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Белгород

Re: Правильный порядок в подцепке

Сообщение Nick »

Проверил на работе:

Select
KatSopr.NSopr, KatSopr.DSopr,
SpSopr.Npp, SpSopr.KolFact, SpSopr.Price,
KatMc.Name
Where
(( 101 /== KatSopr.VidSopr
and KatSopr.Nrec /== SpSopr.cSopr
and SpSopr.cMcUsl /== KatMc.Nrec
))
and (KatSopr.DSopr >= '31/01/2004')
;

Работает и так:
and SpSopr.cMcUsl /== KatMc.Nrec
и так:
and KatMc.Nrec /== SpSopr.cMcUsl

Правда второй вариант гораздо дольше выполняется (260 сек. против 8 сек. в первом случае). Почему так, ведь в теории второй вариант правильнее - слева главная таблица, справа - подчиненная?

Такой вопрос - вообще как работает подцепка? Есть, например, записи в SpSopr и записи в KatMc.

При SpSopr.cMcUsl /== KatMc.Nrec Галактика проходит по SpSopr и:
1. Берет текущее SpSopr.cMcUsl
2. Проходит с текущей SpSopr.cMcUsl по KatMc и цепляет записи KatMc, где SpSopr.cMcUsl = KatMc.Nrec

Получем табличку:

SpSopr - KatMc
SpSopr - KatMc
...
SpSopr - KatMc

При KatMc.Nrec /== SpSopr.cMcUsl Галактика проходит по KatMc и:
1. Берет текущее KatMc.Nrec
2. Проходит с текущей KatMc.Nrec по SpSopr и цепляет записи KatMc, где KatMc.Nrec = SpSopr.cMcUsl

Получем табличку:

KatMc - SpSopr
KatMc - SpSopr
...
KatMc - SpSopr


Т.е. если имеем:
SpSopr KatMc
A 1,2,3
B 4,5

То в первом случае получим:

A - 1
A - 2
A - 3
B - 4
B - 5

Во втором случае получим:

1 - A
2 - A
3 - A
4 - B
5 - B

Это и есть декартово произведение? Результат-то один, но почему скорости разные и правила жесткие в подцепке на расположение таблиц родительских и подчиненных, если в результате получаем один результат?
Maverick
Абориген
Сообщения: 943
Зарегистрирован: 29 мар 2005, 17:49
Откуда: External Developer
Контактная информация:

Re: Правильный порядок в подцепке

Сообщение Maverick »

Святая простота... )))
KatMc.Nrec /== SpSopr.cMcUsl означает лишь отразить те записи из SPSOPR которые есть на данный момент в KatMC, причем KatMC - корневая таблица по отношению к SPSOPR ... При этом нужно еще и не забыть фильтр в SPSOPR по PRMC (что еэто - именно товар - иначе при совпадении нреков могут и услуги отобразиться)

SpSopr.cMcUsl /== KatMc.Nrec - наоборот, отобразить только то, что есть в спецификации - тогда корень - SPSOPR? подчиненная - KATMC.

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

А по сути
Select
KatSopr.NSopr, KatSopr.DSopr,
SpSopr.Npp, SpSopr.KolFact, SpSopr.Price,
KatMc.Name
Where
((
101 /== KatSopr.VidSopr
and KatSopr.Nrec /== SpSopr.cSopr
and SpSopr.cMcUsl /== KatMc.Nrec
));

лучше писать так

Select
KatSopr.NSopr, KatSopr.DSopr,
SpSopr.Npp, SpSopr.KolFact, SpSopr.Price,
KatMc.Name
Where
((
Word(101) == KatSopr.VidSopr
and KatSopr.Nrec == SpSopr.cSopr
and SpSopr.cMcUsl == KatMc.Nrec
));

таким образом данный селект отобразит шапку накладных (номер и дату накладнной)по типу 101, по моему - приходые накладные(KATSOPR), спецификацию (номер п/п, кол-во и цену) по каждой накладной (SPSOPR) где кажой записи из KatSopr будет соответствовать группа записей из SPSopr (1 к N), и МЦ , соответствующую кажддой позиции накладной (KATMC) при этом каждой позиции в SPSOPR соответствует 1 запись из KATMC (связь 1 к 1).
В случае обычного запроса получится плоская табличка с кол-вом записей S*N, где S- кол-во записей в KATSOPR, а S - кол-во записей SPSOPR соответствующее каждой позиции из KATSOPR (KATMC в расчет не берется т.к. связь 1 к 1).
В случае обработки из випа имеем пробежку по корневой KATSOPR - внутри нее - пробежку по SPSOPR а внутри последней - проверка наличия записи в KATMC
Изображение
Знающий людей разумен.
Знающий себя просветлён.
Побеждающий людей силен.
Побеждающий самого себя могущественнен
Maverick
Абориген
Сообщения: 943
Зарегистрирован: 29 мар 2005, 17:49
Откуда: External Developer
Контактная информация:

Re: Правильный порядок в подцепке

Сообщение Maverick »

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


запись наоборот означает что ты пытаешься найти соответствия МЦ-спецификация, т.е. для каждой МЦ из справочника проверяешь, есть ли она в спецификации.. а это имхо - бред, т.к. спецификация формируется именно из справочника
Изображение
Знающий людей разумен.
Знающий себя просветлён.
Побеждающий людей силен.
Побеждающий самого себя могущественнен
bublik
Постоянный гость
Сообщения: 58
Зарегистрирован: 29 мар 2005, 17:49

Re: Правильный порядок в подцепке

Сообщение bublik »

Ув., Maverick! А не подскажете ли как правильно формировать и как работают подцепки в КОРПО-ЗАПРОСАХ ? Вот уж где действительно "темный лес" !!!!!! Может вы "осветите" этот вопрос? Более подробно я описал его в "администраторском форуме". Прошу пардона что влез в вашу разговор...
ecasoft
Местный житель
Сообщения: 645
Зарегистрирован: 29 мар 2005, 17:49
Откуда: г.Королев МО ООО "Эффективная Комплексная Автоматизация- СОФТ"

Re: Правильный порядок в подцепке

Сообщение ecasoft »

SQL Галактики такой вот :)

В WHERE (( )) справа от == (или от <<=, >>=,>>,<<) стоит таблица, которая зависит от значения поля, указанного слева. Если таблица стоит несколько раз справа, то все поля, по которым она подцеплена к левой стороне образуют так называемы составной индекс (должен быть описан в словаре). Такую талицу еще называют узлом. К узлу можно подвесить еще и не индексные условия..

....
WORD(1) == SpSopr.PrMc and
KatMc.Nrec == SpSOpr.cMcUsl
(SpSopr.atl_lastdate = cur_date) and
....
ТАКИМ ОБРАЗОМ, в Галактике, Вы программируете не обычным SQL, а так бы подсказываете интерпретатору, какой поиск использовать явно. При этом стоя эффективный SQl запрос Вы должны отталкиваться от наличия индексов в БД.

Тем, кто рашьне не "помогал" SQL -серверу..все это покажется странным..это нормально. :)
Некоммерческое общение в форуме
bublik
Постоянный гость
Сообщения: 58
Зарегистрирован: 29 мар 2005, 17:49

Re: Правильный порядок в подцепке

Сообщение bublik »

А как же с подцепками в запросах корпо-обмена? Неужели никто не знает как ЭТО работает? Или только мы одни пользуемся запросами в корпообмене?
Maverick
Абориген
Сообщения: 943
Зарегистрирован: 29 мар 2005, 17:49
Откуда: External Developer
Контактная информация:

Re: Правильный порядок в подцепке

Сообщение Maverick »

в обчем, тезка правильно осветил вопрос - емко и в двух словах )))
а еще - RTFM ))) тока очень внимательно )))

по факту то что он сказал можно разделить на две части
а) ограничение на таблицу
слева константа - справа таблица. соединение через ==
б) подцепка через индексное выражение
слева - поле (поля) корневой таблицы, правал - подчиненной. причем порядок полей слева должен в точности до некоторой позиции составлять один ихз существующих индексов. в случае отличия порядка следования полей от порядка, определяемого одним из индексных выражений будет злостная ругань со стороны компилятора. этого можно ихзбежать если использовать вместо == знак = и выражение заключать в скобки. это будет фильтр. только он очень тормозит. луче после несовпадающей с индесом связки писать (noindex)/ но как я понимаю, до этого вам еще далеко
Изображение
Знающий людей разумен.
Знающий себя просветлён.
Побеждающий людей силен.
Побеждающий самого себя могущественнен
ecasoft
Местный житель
Сообщения: 645
Зарегистрирован: 29 мар 2005, 17:49
Откуда: г.Королев МО ООО "Эффективная Комплексная Автоматизация- СОФТ"

Re: Правильный порядок в подцепке

Сообщение ecasoft »

Мы не пользовались. Как-то не нужно было. Да и вообще с корпо мало работаем - большенство на одной площадке сидят. А если удаленно - то полный обмен. Обычно, если удаленное юр. лицо, то полный обмен в ее базу, а с этой базой уже стыкуется головная по документам (типа экспорт-импорт). Удаленных складов чего-то не стало...все протянули провода :)
Некоммерческое общение в форуме
sth
Постоянный обитатель
Сообщения: 148
Зарегистрирован: 29 мар 2005, 17:49

Re: Правильный порядок в подцепке

Сообщение sth »

подцепки в корпо работают также как и в обычном галактическом sql. по сути, это он и есть.
Priest Geo
Посетитель
Сообщения: 30
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Москва/Минск
Контактная информация:

Re: Правильный порядок в подцепке

Сообщение Priest Geo »

В первом случае когда мы имеем подцепку:
...
Where
(( 101 /== KatSopr.VidSopr
and KatSopr.Nrec /== SpSopr.cSopr
and SpSopr.cMcUsl /== KatMc.Nrec ))

просматриваются по порядку ВСЕ SpSopr; берётся первая запись SpSopr и ЕДИНСТВЕННАЯ запись KatMC (по NREC, а раз это по индексу - это быстренько находится)
Во втором случае:
...
Where
(( 101 /== KatSopr.VidSopr
and KatSopr.Nrec /== SpSopr.cSopr
and KatMc.Nrec /== SpSopr.cMcUsl ))

перебираются по очереди ВСЕ записи KatMC и если находится такой что KatMC.Nrec = SpSopr.cMcUsl, то запись оставляется в покое и берётся следующая SpSopr и всё начинается сначала, иначе текущий SpSopr игнорируется.
Вот если бы запрос был немного другой:
...
Where
(( '00001' == KatMC.Barkod
and 101 /== KatSopr.VidSopr
and KatSopr.Nrec /== SpSopr.cSopr
and KatMc.Nrec /== SpSopr.cMcUsl ))
или
...
Where
((
Word(7) == Pick.wList
// выборка полученная через RunInterface('GetSomeMC', (-12345))
and Pick.cRec == KatMC.Nrec
and 101 /== KatSopr.VidSopr
and KatSopr.Nrec /== SpSopr.cSopr
and KatMc.Nrec /== SpSopr.cMcUsl ))
тогда такой запрос имело бы смысл писать, хотя эффективнее изменить его на такой:
...
Where
((
Word(7) == Pick.wList
and word(101) == SpSopr.VidSopr
and Pick.cRec == SpSopr.cMcUsl
and Pick.cRec == KatSopr.Nrec // это если нужно название МЦ
and SpSopr.cSopr == KatSopr.Nrec // это для номера накладной (dSopr есть и в SpSopr)
))
Nick
Местный житель
Сообщения: 331
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Белгород

Re: Правильный порядок в подцепке

Сообщение Nick »

Спасибо всем ответившим 8)
Вроде как разобрался.

Такой вопрос возник по индексам: Выцепляю из накладной, помимо всего, Товарно-транспортную информацию (наименование пункта погрузки):

Select
KatSopr.NSopr, KatSopr.DSopr,
MarPunkt.Name,
SpSopr.Npp, SpSopr.KolFact, SpSopr.Price,
KatMc.Name
Where
((
101 == KatSopr.VidSopr
and KatSopr.nRec == TTNDOC.cDoc (NoIndex)
and TTNDoc.cPunktP == MarPunkt.nRec
and KatSopr.nRec == SpSopr.cSopr
and SpSopr.cMcUsl == KatMc.nRec
));

Хочется все-таки использовать индекс для TTNDoc. У нее есть ближайший похожий: TTNDOC02 - по двум полям: WTABLE и CDOC.

Хочу добавить в выборку строку word(1) << TTNDoc.wTable чтобы все попадало по этому условию в результат, и индекс использовался.
Но Галактика дает этого сделать - ругается, что нужен ключ по WTable + cDoc для TTNDoc ???
А если заменить эту строчку на word(1) == TTNDoc.wTable - нормально все проходит, но естественно в результат ничего не попадает.

Подскажите, можно ли решить, или придется использовать все-таки NoIndex ?
bublik
Постоянный гость
Сообщения: 58
Зарегистрирован: 29 мар 2005, 17:49

Re: Правильный порядок в подцепке

Сообщение bublik »

> sth
> подцепки в корпо работают также как и в
>обычном галактическом sql. по сути, это он
>и есть

Запрос - он везде запрос. И по сути ВСЕ ЗАПРОСЫ работают как ЗАПРОСЫ, т.е. с подцепками, "фильтрацией", "индексами и т.д.
Только вот ПОСТРОЕНИЕ и ФУНКЦИОНИРОВАНИЕ КОРПО-ЗАПРОСА это соооовсем иное. Напишите "по сути" тот же корпо запрос в явном виде в SQL и вы .... НИЧЕГО НЕ ПОЛУЧИТЕ, или же получите БОООЛьшой ступор системы! SQL запрос работает напрямую с таблицами и это РЕАЛЬНЫЙ ЗАПРОС. КОРПО-ЗАПРОС - это построитель/описатель выборок, но никак НЕ ЯВНЫЙ ЗАПРОС! И как я понял, тот кто знал как это работает давно уже помер...
И работает этот запрос не с таблицами, а с журналом - это факт!
Ответить