0
- 26.02.2012 - 11:51
|
8.2.15 Имеем запрос: |ВЫБРАТЬ | ЗаказОконныйГотовыеИзделия.НомерСтроки, | ЗаказОконныйГотовыеИзделия.Конструкция, | ЗаказОконныйГотовыеИзделия.Номенклатура, | ЗаказОконныйГотовыеИзделия.Номенклатура.ПлощадьИзд елия КАК Площадь, | ЗаказОконныйГотовыеИзделия.Количество, | ЗаказОконныйГотовыеИзделия.Сумма |ПОМЕСТИТЬ ИзделияВКонструкции |ИЗ | Документ.ЗаказОконный.ГотовыеИзделия КАК ЗаказОконныйГотовыеИзделия |ГДЕ | ЗаказОконныйГотовыеИзделия.Ссылка = &Заказ | И ЗаказОконныйГотовыеИзделия.Конструкция <> ЗНАЧЕНИЕ(Справочник.Конструкции.ПустаяСсылка) | И НЕ ЗаказОконныйГотовыеИзделия.Конструкция В | (ВЫБРАТЬ | ИзделияВКонструкции.Конструкция | ИЗ | ИзделияВКонструкции) Ругается "Таблица не найдена "ИзделияВКонструкции" Это у меня ошибка, или это "почти скулевский язык запросов" такое не понимает?! | | ||
1
- 26.02.2012 - 12:54
|
Ну ты и завернул... *ошарашено* "Классический" скуль (т.е. стандарт для всех реализаций: MS, IBM, PG...) такое точно кушает? | | ||
2
- 26.02.2012 - 13:02
|
2-VZ >Насчёт "классического" ничего не скажу, но все, с которыми я работал, очень даже неплохо справляются с этим. Что тут необычного, сверяться в insertе с данными из таблицы, в которую этот insert делается? Очень даже распрастранённый способ. | | ||
3
- 26.02.2012 - 13:04
|
Вот рабочий запрос из MS-SQL |if exists(select * from tempdb..sysobjects where id = object_id('tempdb..#Группы')) | drop table #Группы | create table #Группы (val char(9), primary key clustered (val)) |set nocount on |declare @Контр table(val char(9), isfolder tinyint, primary key clustered (val)) |insert @Контр values (:ВыбГруппа, 1) |while 1=1 |begin | insert into #Группы | select val | from @Контр | where isfolder = 1 and val not in ( select val from #Группы ) | if @@rowcount = 0 break | insert into @Контр | select id,isfolder | from sc133 (nolock) | where parentid in (select val from #Группы ) | and id not in ( select val from @Контр ) | and isfolder=1 | delete @Контр | where val in (select val from #Группы) |end |set nocount off | | ||
4
- 26.02.2012 - 13:07
|
Не, я конечно решил проблему из (0), это ни вопрос. Просто я не думал, что в этом может возникнуть проблема :) | | ||
5
- 26.02.2012 - 13:11
| зациклено, выбрать из того, во что поместить. Пакетный запрос сделай | | ||
6
- 26.02.2012 - 13:14
|
6-Jimbo >Ну попробуй, сделай через пакет :) Я же сказал, что вопрос ни в том как это сделать, а в том, почему нельзя читать данные из временной таблицы во время записи в неё? | | ||
7
- 26.02.2012 - 13:15
| потому что гладиолус. 1с только выбирать может, инсертить никак | | ||
8
- 26.02.2012 - 13:18
|
8-Jimbo >Я знал что многое запущено. Но ни думал, что настолько :) | | ||
9
- 26.02.2012 - 13:18
| и как-то нехорошо: вначале идентификатор ИзделияВКонструкции объявляешь в ПОМЕСТИТЬ, а потом этот же идентификатор как динамический массив (в (Выбрать из...) | | ||
10
- 26.02.2012 - 13:18
|
пакет : 1-я выборка 2-я выборка то, что не входит в первую | | ||
11
- 26.02.2012 - 13:19
|
Да ещё, одно. Почему нельзя дописать данные в существующую временную таблицу? Мне это тоже не понятно. Или я ошибаюсь? | | ||
12
- 26.02.2012 - 13:20
| рекомендую про запросы посмотреть видео от Павла Чистова. Как минимум 3 лекции | | ||
13
- 26.02.2012 - 13:20
| +10 Но это потому так думаю, что такие кульбиты не исполнял ;( | | ||
14
- 26.02.2012 - 13:23
| 5-Billi > А как все-таки "правильно"? Для 1С, естественно :) | | ||
15
- 26.02.2012 - 13:23
|
10-VZ >И чего же в этом нехорошего? Посмотри пример из (4) | insert into #Группы | select val | from @Контр | where isfolder = 1 and val not in ( select val from #Группы ) Всё замечателно работает. | | ||
16
- 26.02.2012 - 13:24
|
15-VZ >Я сделал вот так: "ВЫБРАТЬ | Подзапрос.НомерСтроки, | Подзапрос.Конструкция, | ЗаказОконныйГотовыеИзделия.Номенклатура, | ЗаказОконныйГотовыеИзделия.Номенклатура.ПлощадьИзд елия КАК Площадь, | ЗаказОконныйГотовыеИзделия.Количество, | ЗаказОконныйГотовыеИзделия.Сумма |ПОМЕСТИТЬ ИзделияВКонструкции |ИЗ | (ВЫБРАТЬ | ЗаказОконныйГотовыеИзделия.Конструкция КАК Конструкция, | МИНИМУМ(ЗаказОконныйГотовыеИзделия.НомерСтроки) КАК НомерСтроки | ИЗ | Документ.ЗаказОконный.ГотовыеИзделия КАК ЗаказОконныйГотовыеИзделия | ГДЕ | ЗаказОконныйГотовыеИзделия.Ссылка = &Заказ | И ЗаказОконныйГотовыеИзделия.Конструкция <> ЗНАЧЕНИЕ(Справочник.Конструкции.ПустаяСсылка) | | СГРУППИРОВАТЬ ПО | ЗаказОконныйГотовыеИзделия.Конструкция) КАК Подзапрос | ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказОконный.ГотовыеИзделия КАК ЗаказОконныйГотовыеИзделия | ПО (ЗаказОконныйГотовыеИзделия.Ссылка = &Заказ) | И (ЗаказОконныйГотовыеИзделия.НомерСтроки = Подзапрос.НомерСтроки) | | ||
17
- 26.02.2012 - 13:26
| (16) - кто тебе сказал что 1с = полноценный SQL? в 1с очень упрощенный язык, читаем ЖКК. | | ||
18
- 26.02.2012 - 13:28
|
15-VZ >Но ты сам видишь, что элегантности в (17) маловато. Хотя можно было бы от соединения отказаться, всё в подзапросе сделать. | | ||
19
- 26.02.2012 - 13:28
| 18-Jimbo >я же написал "почти скулевский язык запросов" :) | | ||
20
- 26.02.2012 - 13:34
| 17-Billi > Спасибо. Да, исходное очень элегантно. Жаль, что не работает. | | ||
21
- 26.02.2012 - 13:44
|
21-VZ >Я примерно догадываюсь, почему не работает. 1с вообще не любит поручать работу скл-серверу. Наровит всё сама сделать. Поэтому функционал временных таблиц очень ограничен. Я думаю, что они его создали, только для того, чтобы ТЗ в запросах могли учавствовать. Ну и ещё чего-нибудь, по мелочи. Я полагаю, что мою ситуацию надо было решать так: вытащить тч документа в саму 1с (запросом или напрямую из объекта), обработать её в 1с-ке, и затем результат отправить запросом во временную таблицу. | | ||
22
- 26.02.2012 - 14:11
|
Приведенное сравнение, мягко говоря, некорректно. Конструкция из (4) не выполняет динамический анализ вставляемых данных. Именно поэтому ты используешь цикл. Ничего не мешает выполнять ровно такой же цикл в конструкциях временных таблиц 1С. (12) Потому что 1С вообще ничего не инсертит на уровне запросов. Все обработки по пополнению агрегатов выполняются на уровне сервера 1С, а не на уровне SQL сервера. Следовательно, ничего не инсертнешь и во временную таблицу. Кроме того, в приведенном тобой примере, инсертить - крайне низко производительно. Гораздо производительнее таблицу #Группы дропать каждый раз и генерировать заново. И тебя же там кластерный индекс, по которому системе приходится каждый раз перестравивать табличку. ЗЫ: За запрос в (4) вообще убивать хочется. | | ||
23
- 26.02.2012 - 14:24
|
(17) За этот запрос тоже по крайней мере побил бы. Накой тебе тут ЛЕВОЕ СОЕДИНЕНИЕ??? Оно ж тормознутее внутреннего, а смысла тут в нем никакого! Сделай через внутреннее, посмотри план выполнения на SQL и изумись четкости и однозначности прекрасной связки 1С + MS SQL. Она отработает просто идеально. (21) Исходное - полный бред и в рамках кучу ни имеет ничего общего с кокретной задачей из (17). (22) Опять непонимае механизмов взаимодействия трезвенки. Это твое предложение потягать таблицу туда-сюда-обратно выльется в большой объем трафика БД-сервер 1С - а может даже и на толстого клиента. Механизм временных таблиц позволяет радикально снизить объем передачи данных между серверами и клиентов, локализовав обработку бизнес-логики извлечения данных на уровне SQL. По причине необходимости содержания такого огромного и тяжелого встроенного языка в модулях проведения и обработчиках ПриЗаписи, 1С не дает нам ничего изменять в таблицах. Соответственно под этот каток попали и временные таблицы. Хотя в этом смысла, действительно, нет никакого. А так большего функционала с tt в SQL и нет, если смотреть на возможности работы 1С с таблицами SQL прикладных объектов. | | ||
24
- 26.02.2012 - 14:27
|
23-Lexusss >Ты хочешь сказать, что кусок кода в (16) не выполняет динамический анализ вставляемых данных? Посмотри ещё раз внимательно и подумай хорошенько. :) Цитата:
А твою реплипку насчет убийств за (4) я вообще без коммента оставлю :)))) | | ||
25
- 26.02.2012 - 14:28
| В догонку еще один гвоздь в крышку - группы контрагентов в 95% случаев это большое зло. Нужно очень осторожно подходить к их созданию либо же использовать нестандартные механизмы работы со списками справочников. | | ||
26
- 26.02.2012 - 14:31
| Цитата:
Цитата:
Если у тебя есть понимание, то ответь на (12) | | ||
27
- 26.02.2012 - 14:33
| 26-Lexusss >Ну вот тут ты точно добил гвоздь в крышку :D | | ||
28
- 26.02.2012 - 15:13
|
(25) Не выполняется проверка. У тебя @Контр уникальна по id. Причина моего страстного желания убрать авторов подобных творений из IT (пусть и ценой убийства) - это стремление к идеалу. Вот скажи, зачем ты каждый раз в итерации выполняешь снова и снова обработку всех контрагентов по всем группам сгенерированной иерархии? Ведь достаточно сделать это ОДИН раз, а в итерации обрабатывать только новый сред иерархии. Так получается и код проще, да и вообще понять проще :) (27) Для особо не понятливых. Ты из таблицы А выбираешь часть строк и после этого присоединяешь снова всю таблицу А. То есть множество строк первой соединяемой таблицы однозначно меньше множества строк второй соединяемой таблицы. В это случае ЛЕВОЕ и ВНУТРЕННЕЕ соединения дадут одинаковый результат. Но производительность второй конструкции намного выше производительности первой. Кроме того, такое соединение может повлечь оптимизатору построить кривой план выполнения. Предположим такую гипотетическую интерпретацию запроса (1), что в куче Документ.ЗаказОконный.ГотовыеИзделия в выборку первой попадет строка с НомерСтроки = 2, а не строка с НомерСтроки = 1. В этом случае, твоя интерпретация запроса (1) не совпадет с результатом запроса (17). Смотри мой 23й пост. ПЫСЫ: Зачем ветку наверх пришпили? | | ||
29
- 26.02.2012 - 15:17
| (28) Про потребность и необходимость иерархии можно спорить безумно долго. Но моя практика использования 7.7 толпами пользователей говорит, что существование папок в контрагентах ведет к их гарантированном задвоению. Чтобы добавить в 7.7 нового контрагента, нужно было включать иерархию. А вот отключить ее для поиска контрагента перед созданием новой карточки, многие пользователи забывают. Отсюда дубляжи с последующими проблемами. В 8.х это проблема понерфлена , но все еще актуальна. | | ||
30
- 26.02.2012 - 15:50
|
29-Lexusss > Цитата:
Для особо непонятлевых читай (19) внимательно, вторую строчку. Цитата:
Ещё раз повторю, про агрегаты речи не было. А во временные таблицы инсерт идёт именно на уровне скл. Тем более в пакете. И я не вижу никаких особых препятствий для того, чтобы сделать возможность дополнять временные таблицы. 30-Lexusss >Спорить не буду. Ибо предмета спора нет. Проблема решается элементарно. | | ||
31
- 26.02.2012 - 15:52
|
29-Lexusss >"Зачем ветку наверх пришпили?" Временно. Использую "служебное положение", что бы легче посматривать :) Извините. | | ||
32
- 26.02.2012 - 16:54
|
На счёт (0) скажу, что это действительно ерунда. При простом инсерте скл динамически не отслеживает новые записи в таблице. Решить задачу в (0) на скл без дополнительных группировок и соединений можно через уникальный индекс по полю "Конструкция". | | ||
33
- 26.02.2012 - 17:02
| Понеслась читать логику запроса. Исходные данные: таблицы sc133 справочника Контрагенты с индексами по id и parentid. Требуемый результат - все группы, входящие в иерархию группы с id ВыбГруппа. Используемые временные таблицы: #Группы - результирующая таблица #Контр - таблица текущего среза В ходе каждой итерации выполняются 3 запроса (insert into Группы, insert into Контр, delete Контр Первая итерация: Запрос 1: бессмысленная нагрузка на сервер. Можно добиться того же просто вставкой конкретного значения в Группы. Запрос 2: Берет срез групп, вложенных в ВыбГруппа и добавляет их в Контр. Обратим внимание, что в Контр id кластеризованый. То есть при такой вставке таблица будет жестко перестроена с потерей балансировки B-дерева кластерного индекса. Уникальность добавленных строк обеспечивается отдельной конструкцией "id not in ( select val from @Контр )" Запрос 3 опять же ничего не делает, лишь позря напрягает SQL. Итерация n+1: Запрос 1 добавляет в Группы НОВЫЕ значения из Контр. Там они так же уникальны по id, так что проверки в процессе добавления может и не происходить. Очень интересна проверка на isfolder, как будто там может быть что то другое :D Запрос 2 выбирает срез групп на уровне вложенности n. Опять выполняется какая то странная проверка " id not in ( select val from @Контр )". Конечно, это опять же гарантирует уникальность id в Контр, но зачем??? Разве, что у вас нарушена древовидность иерархии. Запрос 3, о чудо, удаляет из Контр данные итоговой таблицы, полученные на прошлой итерации!!! Опять же при этом портится чудесное b-дерево кластерного индекса. Именно из этого следует вопрос: Почему бы табличку текущего среза не прибить и не перегенрировать заново? Тогда не придется выполнять эти delete с просмотром всей Контр снова и снова. Итого, для простейшего случая без детей или с один уровнем вложенности, у тебя получается очень большая доля бессмысленных операций. Кроме того, над временной таблицей выполняется огромное количество операций insert и delete, при том что собственно кластерный индекс по id совершенно не используется. | | ||
34
- 26.02.2012 - 17:11
| У тебя в (17) правильный запрос, кроме косяка с ЛЕВЫМ соединением. На SQL он будет отрабатывать оптимальным образом. Проверялось на огромных таблицах (миллионы строк). Никакие другие методы с временными таблицами, индексами и прочей лабудой и рядом не стоят. Вложенный запрос разворачивается оптимизатором SQL в такой же план выполнения (если мы говорим о грамотно написанном запросе). Время выполнения вообще не отличается. Если уж выбираешь сумму и количество, как то странно такое слышать. Уж извини, не угадал... Я тож не прочь увидеть INSERT в 1С, хотя бы в каком то виде. Но пока что обхожусь без этого без особых потерь производительности. | | ||
35
- 26.02.2012 - 17:16
|
(33) Про уникальный индекс поподробнее. Неужели SQL не ругнется на DUPLICATED RECORD (или типа того)? Как то слабо верится. Я сейчас очень далек от серверов и не на чем экспериментировать. Тем не менее я рад, что мое предположение о невозможности динамического отслеживания добавления записей оправдалось :) Если оптимизатор SQL мог бы и такое, он вошел бы в пантеон моих богов. Как в таком случае строить план выполнения - это выше моих представлений о всем сущем. | | ||
36
- 26.02.2012 - 17:18
|
(32) Воскресенье, особой активности нет, следить за веткой очень просто. Так что, конечно же, извиняю. Обещаю в ветке не материться и не переводить в holly war "клюшки vs снеговик" :D))) | | ||
37
- 26.02.2012 - 17:35
| 37-Lexusss >Спасибо :D | | ||
38
- 26.02.2012 - 17:36
|
34-Lexusss >На всякий случай скажу, что это не моё произведение, я им просто пользуюсь :) Механизм работает исправно, 100 000 контров в 300-ах группах, тормозов в этом месте незамечено. А теоретически конечно интересно порассуждать. Если что, то я на стороне того парня :) Позже отпишусь по этому вопросу. 35-Lexusss >вобще-то в (17) левое соединение поставила сама одиныска в конструкторе :), я на автомате в форум и скопировал. А соединение я добавил потому как не люблю лишние группировки. А затем подумал, что соединение вообще не нужно, можно и все поля включать в подзапрос, там записей от силы 10 штук будет, так что группировка доп.полей сильно не навредит :) Там всё просто. В конструкции есть доп.элементы, которые не относятся ни к какому изделию (номенклатура), входящему в конструкцию, и сами по себе изделиями не являются. Вот их и надо в состав какой-нибудь номенклатуры воткнуть, не важно какой. Это делается один раз и записывается в РС сотав изделия, и они потом спокойно существуют в этом составе. | | ||
39
- 26.02.2012 - 17:48
| 36-Lexusss >Чуть позже отвечу. | |
| Интернет-форум Краснодарского края и Краснодара |