К списку форумов К списку тем
Регистрация    Правила    Главная форума    Поиск   
Имя: Пароль:
Рекомендовать в новости

Ошибка в запросе. Это так и должно быть?!

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) не выполняет динамический анализ вставляемых данных?
Посмотри ещё раз внимательно и подумай хорошенько. :)

Цитата:
Сообщение от Lexusss Посмотреть сообщение
Потому что 1С вообще ничего не инсертит на уровне запросов. Все обработки по пополнению агрегатов выполняются на уровне сервера 1С, а не на уровне SQL сервера. Следовательно, ничего не инсертнешь и во временную таблицу.
Про агрегаты речи не было. Речь шла о временных таблицах, а туда инсерт идет на уровне скл.

А твою реплипку насчет убийств за (4) я вообще без коммента оставлю :))))
Гость
25 - 26.02.2012 - 14:28
В догонку еще один гвоздь в крышку - группы контрагентов в 95% случаев это большое зло. Нужно очень осторожно подходить к их созданию либо же использовать нестандартные механизмы работы со списками справочников.
26 - 26.02.2012 - 14:31
Цитата:
Сообщение от Lexusss Посмотреть сообщение
(17) За этот запрос тоже по крайней мере побил бы. Накой тебе тут ЛЕВОЕ СОЕДИНЕНИЕ??? Оно ж тормознутее внутреннего, а смысла тут в нем никакого! Сделай через внутреннее, посмотри план выполнения на SQL и изумись четкости и однозначности прекрасной связки 1С + MS SQL. Она отработает просто идеально.
Ты ветку читай внимательно, прежде чем отвечать. :)

Цитата:
Сообщение от Lexusss Посмотреть сообщение
(21) Исходное - полный бред и в рамках кучу ни имеет ничего общего с кокретной задачей из (17).
Видать не вник ты в задачу :)
Цитата:
Сообщение от Lexusss Посмотреть сообщение
...
Если у тебя есть понимание, то ответь на (12)
27 - 26.02.2012 - 14:33
26-Lexusss >Ну вот тут ты точно добил гвоздь в крышку :D
Гость
28 - 26.02.2012 - 15:13
(25) Не выполняется проверка. У тебя @Контр уникальна по id.
Причина моего страстного желания убрать авторов подобных творений из IT (пусть и ценой убийства) - это стремление к идеалу.
Вот скажи, зачем ты каждый раз в итерации выполняешь снова и снова обработку всех контрагентов по всем группам сгенерированной иерархии? Ведь достаточно сделать это ОДИН раз, а в итерации обрабатывать только новый сред иерархии. Так получается и код проще, да и вообще понять проще :)
(27)
Цитата:
Сообщение от Billi Посмотреть сообщение
Ты ветку читай внимательно
Для особо не понятливых. Ты из таблицы А выбираешь часть строк и после этого присоединяешь снова всю таблицу А. То есть множество строк первой соединяемой таблицы однозначно меньше множества строк второй соединяемой таблицы. В это случае ЛЕВОЕ и ВНУТРЕННЕЕ соединения дадут одинаковый результат. Но производительность второй конструкции намного выше производительности первой. Кроме того, такое соединение может повлечь оптимизатору построить кривой план выполнения.
Цитата:
Сообщение от Billi Посмотреть сообщение
Видать не вник ты в задачу
Предположим такую гипотетическую интерпретацию запроса (1), что в куче Документ.ЗаказОконный.ГотовыеИзделия в выборку первой попадет строка с НомерСтроки = 2, а не строка с НомерСтроки = 1. В этом случае, твоя интерпретация запроса (1) не совпадет с результатом запроса (17).
Цитата:
Сообщение от Billi Посмотреть сообщение
ответь на (12)
Смотри мой 23й пост.
ПЫСЫ: Зачем ветку наверх пришпили?
Гость
29 - 26.02.2012 - 15:17
(28) Про потребность и необходимость иерархии можно спорить безумно долго. Но моя практика использования 7.7 толпами пользователей говорит, что существование папок в контрагентах ведет к их гарантированном задвоению. Чтобы добавить в 7.7 нового контрагента, нужно было включать иерархию. А вот отключить ее для поиска контрагента перед созданием новой карточки, многие пользователи забывают. Отсюда дубляжи с последующими проблемами. В 8.х это проблема понерфлена , но все еще актуальна.
30 - 26.02.2012 - 15:50
29-Lexusss >
Цитата:
Сообщение от Lexusss Посмотреть сообщение
Вот скажи, зачем ты каждый раз в итерации выполняешь снова и снова обработку всех контрагентов по всем группам сгенерированной иерархии? Ведь достаточно сделать это ОДИН раз, а в итерации обрабатывать только новый сред иерархии. Так получается и код проще, да и вообще понять проще :)
Я не могу тебя понять. Поясни на примере.

Цитата:
Сообщение от Lexusss Посмотреть сообщение
Для особо не понятливых
Для особо непонятлевых читай (19) внимательно, вторую строчку.
Цитата:
Сообщение от Lexusss Посмотреть сообщение
Предположим такую гипотетическую интерпретацию запроса (1), что в куче Документ.ЗаказОконный.ГотовыеИзделия в выборку первой попадет строка с НомерСтроки = 2, а не строка с НомерСтроки = 1. В этом случае, твоя интерпретация запроса (1) не совпадет с результатом запроса (17).
Мне не важно какая строка будет. Мне надо по одной любой строке на каждую Конструкцию.
Цитата:
Сообщение от Lexusss Посмотреть сообщение
Смотри мой 23й пост.
Ещё раз повторю, про агрегаты речи не было.
А во временные таблицы инсерт идёт именно на уровне скл. Тем более в пакете. И я не вижу никаких особых препятствий для того, чтобы сделать возможность дополнять временные таблицы.

30-Lexusss >Спорить не буду. Ибо предмета спора нет. Проблема решается элементарно.
Гость
31 - 26.02.2012 - 15:52
29-Lexusss >"Зачем ветку наверх пришпили?"
Временно. Использую "служебное положение", что бы легче посматривать :)
Извините.
32 - 26.02.2012 - 16:54
На счёт (0) скажу, что это действительно ерунда.
При простом инсерте скл динамически не отслеживает новые записи в таблице.
Решить задачу в (0) на скл без дополнительных группировок и соединений можно через уникальный
индекс по полю "Конструкция".
Гость
33 - 26.02.2012 - 17:02
Цитата:
Сообщение от Billi Посмотреть сообщение
Поясни на примере.
Понеслась читать логику запроса. Исходные данные: таблицы 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
Цитата:
Сообщение от Billi Посмотреть сообщение
Для особо непонятлевых читай (19) внимательно, вторую строчку.
У тебя в (17) правильный запрос, кроме косяка с ЛЕВЫМ соединением. На SQL он будет отрабатывать оптимальным образом. Проверялось на огромных таблицах (миллионы строк). Никакие другие методы с временными таблицами, индексами и прочей лабудой и рядом не стоят. Вложенный запрос разворачивается оптимизатором SQL в такой же план выполнения (если мы говорим о грамотно написанном запросе). Время выполнения вообще не отличается.
Цитата:
Сообщение от Billi Посмотреть сообщение
Мне надо по одной любой строке
Если уж выбираешь сумму и количество, как то странно такое слышать. Уж извини, не угадал...
Цитата:
Сообщение от Billi Посмотреть сообщение
И я не вижу никаких особых препятствий
Я тож не прочь увидеть 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 штук будет, так что группировка доп.полей сильно не навредит :)
Цитата:
Сообщение от Lexusss Посмотреть сообщение
Если уж выбираешь сумму и количество, как то странно такое слышать. Уж извини, не угадал...
Там всё просто. В конструкции есть доп.элементы, которые не относятся ни к какому изделию (номенклатура), входящему в конструкцию, и сами по себе изделиями не являются. Вот их и надо в состав какой-нибудь номенклатуры воткнуть, не важно какой. Это делается один раз и записывается в РС сотав изделия, и они потом спокойно существуют в этом составе.
39 - 26.02.2012 - 17:48
36-Lexusss >Чуть позже отвечу.


К списку вопросов






Copyright ©, Все права защищены