![]() |
![]() |
|
Поиск номенклатуры в большом количестве документов | ☑ | ||
---|---|---|---|---|
0
DarkFrenzy
29.11.10
✎
10:25
|
Каким образом быстрее всего найти все документы (общее количество документов за месяц - ~8000), содержащие в своей табличной части определенную номенклатуру (в базовом отчете "реестр документов" для ТиС 2.0 потребовалось добавить поле ТМЦ/группа)?
Сначала сделал это просто перебором всех документов и всех элементов табличной части (Док.ПолучитьСтроку()=1 и Док.ПолучитьАтрибут) - отчет обрабатывался слишком долго. Затем попробовал выгружать колонку с номенклатурой, если она существует в список значений и искать там с помощью НайтиЗначение() - на локальном компьютере выполнялось быстрее, а на сервере еще дольше чем предыдущий вариант. 1С изучаю всего месяц, поэтому быстродействие для меня пока что темный лес. Сейчас вот думаю попробовать через запрос. Может подскажете,как сделать, чтобы отчет обрабатывался быстрее всего? |
|||
1
JeHer
29.11.10
✎
10:26
|
>>>Сейчас вот думаю попробовать через запрос
Верной дорогой идете, товарищ! |
|||
2
Ёпрст
гуру
29.11.10
✎
10:27
|
(0)
Запрос к регистру с фильтром на номенклатуру, из него - документ движения регистра. Запрос лучше прямой. |
|||
3
inka
29.11.10
✎
10:28
|
а через поиск ссылок не подходит?
|
|||
4
DarkFrenzy
29.11.10
✎
10:32
|
>>Запрос к регистру с фильтром на номенклатуру, из него - документ движения регистра.
Там список всех документов из метаданных, многие даже поле номенклатуры не содержат. Может я и туплю, но по идее они не все связаны с регистрами. |
|||
5
Ёпрст
гуру
29.11.10
✎
10:36
|
(3) штатно - это не быстро в большой базе, но можно переписать на прямой запрос.. Только вот нафига ?
(4) в Тис-е всегда есть хотя бы 1 регистр в котором участвует Номенклатура, который толкают все документы, содержащие Номенклатуру в реквизите. |
|||
6
Злой Бобр
29.11.10
✎
10:37
|
(4) Точно тупишь. Попробуй более точно указать что нужно, тогда и получишь более точную рекомендацию.
|
|||
7
Skom
29.11.10
✎
10:39
|
Select distinct
Рег.IDDOC From $Регистр.Продажи as Рег (nolock) Where $Рег.Номенклатура = :ВыбНоменклатура как то так...лень проверять |
|||
8
DarkFrenzy
29.11.10
✎
10:39
|
>>а через поиск ссылок не подходит?
Как раз сейчас пытаюсь разобраться как работает "НайтиСсылки(<Объекты>,<Ссылки>)", так как в запрос надо передавать большое количество видов документов, выбранных пользователем. Правда не уверен еще, что НайтиСсылки используется именно для этого:) |
|||
9
Skom
29.11.10
✎
10:41
|
в общем. у тебя в ТиС есть регистр продажи (оборотный) в котором фиксируются все продажи (а так же и возвраты) номенклатуры.
(перемещения там не учитываются) просто оттуда выбери ДВИЖЕНИЯ с расходом нужной тебе номенклатуры если прямым запросом то на мой не смотри. делай сам. я там фигню всякую написал)))) если штатным то я не умею им пользоваться...забыл((( в общем ВПЕРЕД!!! |
|||
10
Skom
29.11.10
✎
10:42
|
(8) если у тя ТИПОВАЯ ТиС тогда ФАКТ ПРОДАЖИ товара фиксируется в регистре ПРОДАЖИ (оборотный)
|
|||
11
DarkFrenzy
29.11.10
✎
10:45
|
>>Точно тупишь. Попробуй более точно указать что нужно, тогда и получишь более точную рекомендацию.
Имеется изначальный список документов, содержащий в себе все виды документов метаданных. Пользователь может убирать ненужные документы из этого списка и выбирать период с какой и по какую дату искать. В базовой версии поиск можно вести по Фирме, Автору, Юр.Лицу, Проекту, Контрагенту и Складу. Также можно указать отбор по статусу (проведенные, не проведенные, помеченные на удаление) А нужно добавить возможность поиска по ТМЦ или группе ТМЦ из табличной части документа "номенклатура". |
|||
12
DarkFrenzy
29.11.10
✎
10:47
|
>> если у тя ТИПОВАЯ ТиС тогда ФАКТ ПРОДАЖИ товара фиксируется в регистре ПРОДАЖИ (оборотный)
Документы могут быть и не проведенные |
|||
13
Skom
29.11.10
✎
10:49
|
уточнять надо было
|
|||
14
Skom
29.11.10
✎
10:51
|
прямой запрос тебя спасет в этом плане
|
|||
15
DarkFrenzy
29.11.10
✎
10:55
|
>>прямой запрос тебя спасет в этом плане
А не подскажешь как в него передать список видов обрабатываемых документов, с учетом того, что не все содержать в табличной части графу "номенклатура"? |
|||
16
Ёпрст
гуру
29.11.10
✎
10:57
|
(11) если штатно - то слепи графу отбора, добавь нужные виды документов для неё и привет.
|
|||
17
Mikeware
29.11.10
✎
10:58
|
(15) Ну и сформируй этот список. В чем проблема?
|
|||
18
Mikeware
29.11.10
✎
10:59
|
(16) Ты представь накладняк....
|
|||
19
Ёпрст
гуру
29.11.10
✎
10:59
|
(18) :)
|
|||
20
palpetrovich
29.11.10
✎
10:59
|
(0) "1С изучаю всего месяц..." мдя, одно из двух, или все-же не месяц или автор - вундеркинд :)
|
|||
21
Злой Бобр
29.11.10
✎
11:00
|
(11) Тогда задам тупой вопрос - а как ты будешь определять реквизит документа по которому проверять есть там твое ТМЦ или нет?
|
|||
22
Mikeware
29.11.10
✎
11:00
|
А чего тут вунндеркндного?
|
|||
23
palpetrovich
29.11.10
✎
11:02
|
(22) перечитай его посты ...после месяца изучения - я-бы сказал - посты не мальчика, но мужа :)
|
|||
24
Злой Бобр
29.11.10
✎
11:02
|
(20) Чипсы и кола делают с людьми и не такое.
|
|||
25
Mikeware
29.11.10
✎
11:04
|
(23) Ну, на 1с не только дятлы переходят....
|
|||
26
DarkFrenzy
29.11.10
✎
11:07
|
>>Ну и сформируй этот список. В чем проблема?
Список то есть. Только вот не в одном примере, я не видел как этот список передается в запрос. Поясню |Номенклатура = Документ.СписаниеТМЦ.номенклатура, Документ.ПоступлениеТМЦ.номенклатура, ... и т.д.; - это если вручную прописывать, а как не вручную сделать? |
|||
27
Ёпрст
гуру
29.11.10
✎
11:08
|
(26) через обход метаданных.
|
|||
28
DarkFrenzy
29.11.10
✎
11:12
|
>>"1С изучаю всего месяц..." мдя, одно из двух, или все-же не месяц или автор - вундеркинд :)
Просто стоит задача как можно быстрее его освоить, вот и долблюсь по 7 часов в день. |
|||
29
palpetrovich
29.11.10
✎
11:15
|
(28) это реальная задача или потренироваться?
|
|||
30
DarkFrenzy
29.11.10
✎
11:16
|
>>(28) это реальная задача или потренироваться?
Реальная:) |
|||
31
palpetrovich
29.11.10
✎
11:20
|
(30) тогда нелишней будет информайця файловый у тебя вариант базы или скульный
|
|||
32
Shaman100M
29.11.10
✎
11:21
|
||||
33
Shaman100M
29.11.10
✎
11:23
|
+ (32) Это "Поиск значений в ТЧ доков". Перебираю метаданные и формирую запрос по всем документам где содержится вид поискового значения. Работает достаточно быстро.
|
|||
34
DarkFrenzy
29.11.10
✎
11:32
|
>>тогда нелишней будет информайця файловый у тебя вариант базы или скульный
Файловый >>+ (32) Это "Поиск значений в ТЧ доков". Спасибо, уже скачивал эту обработку, запускал - работает хоть и быстрее, но незначительно (прирост производительности около 10-15% был на сколько я помню по сравнением с тем, что у меня). |
|||
35
Злой Бобр
29.11.10
✎
11:40
|
(34) Ну а что ты хотел? 8 тыщ это фигня а не объем. Было б у тебя в день 8 тыщ - тогда б и был смысл заморачиваться с ускорением. А так +,- 10 сек. - особой роли неиграет.
|
|||
36
palpetrovich
29.11.10
✎
11:42
|
(34) раз файловый - стало-быть надо смотреть в сторону 1sqlite. Это библтотека, позовляющая напряму обращаться к таблицам базы, "прямы запросы" как говорилось выше
|
|||
37
DarkFrenzy
29.11.10
✎
11:52
|
>>Ну а что ты хотел? 8 тыщ это фигня а не объем. Было б у тебя в день 8 тыщ - тогда б и был смысл заморачиваться с ускорением. А так +,- 10 сек. - особой роли неиграет.
В том то и дело, что я понятия не имею сколько времени этот отчет должен обрабатываться при правильно написанном коде. Долгое время обработки я списываю на свои недостаточные знания языка 1с и оптимизации. Если срок обработки скажем в 3 минуты - это нормальное явление, конечно нет особого смысла заморачиваться. Если его можно свести к 20 секундам, то есть. |
|||
38
Злой Бобр
29.11.10
✎
11:54
|
(37) На прямом запросе я думаю должно в среднем отрабатывать за 10-30 сек., в зависимости отколичества и значений фильтров.
|
|||
39
palpetrovich
29.11.10
✎
11:55
|
+36: для одного вида документа будет выглядеть примерно так (я сам не спец в прямых, может поправят, добавят кто...):
Попытка базаДанных = СоздатьОбъект("SQLiteBase"); Исключение ЗагрузитьВнешнююКомпоненту("1sqlite.dll"); базаДанных = СоздатьОбъект("SQLiteBase"); КонецПопытки; базаДанных.Открыть(":memory:"); Запрос = базаДанных.НовыйЗапрос(); запрос.ВыполнитьЗапрос("PRAGMA journal_mode = OFF"); Запрос.ВыполнитьЗапрос("create virtual table ДокРН using dbeng(ДокументСтроки.РасходнаяНакладная)"); Запрос.Подготовить(" |SELECT |Док.IDDoc [Докум :Документ.РасходнаяНакладная], |Док.Номенклатура [Номенклатура :Справочник.Номенклатура] |FROM ДокРН Док |WHERE Док.Номенклатура = @ВыбрТовар |"); запрос.УстановитьПараметр("@ВыбрТовар", ВыбрНоменклатура); Попытка тз=запрос.Выполнить(); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; тз.ВыбратьСтроку(); ну и саму 1sqlite.dll надо скачать и кинуть в базу |
|||
40
Skom
29.11.10
✎
12:03
|
(15)
Стр = ВыбранныеДокументы.ВСтрокуСРазделителями(); фильтрДоков = СтрЗаменить(Стр,"""",""); Если фильтрДоков <> "" Тогда ТекстЗапроса=ТекстЗапроса+" |AND Жур.IDDocDef in ("+фильтрДоков+")"; КонецЕсли; ВыбранныеДокументы - элемент на форме СПИСОК С ПОМЕТКАМИ в котором пользователи выбираюткаки виды доков обрабатывать |
|||
41
Skom
29.11.10
✎
12:05
|
ВыбранныеДокументы.ДобавитьЗначение("$ВидДокумента."+Метаданные.Документ(Инд).Идентификатор,Метаданные.Документ(Инд).Представление());
а вот это внутри списка |
|||
42
DarkFrenzy
29.11.10
✎
12:07
|
Спасибо, пойду разбираться что собой представляет 1sqlite
|
|||
43
Skom
29.11.10
✎
12:08
|
(42) я для MSSQL все это делал
с лайтом не знаю мои коды прокатят или нет. |
|||
44
Skom
29.11.10
✎
12:08
|
+(43) глянул (39) и подумал
а не пойти ли восьмерку учить))))) |
|||
45
DarkFrenzy
29.11.10
✎
14:37
|
>>Тогда задам тупой вопрос - а как ты будешь определять реквизит документа по которому проверять есть там твое ТМЦ или нет?
Пропустил вопрос. Там только 2 варианта может быть, либо в документе есть реквизит "номенклатура", либо его нету. В других реквизитах искать не имеет смысла - для всех документов, где есть ТМЦ используется один и тот же реквизит "номенклатура". |
|||
46
Злой Бобр
29.11.10
✎
15:10
|
(45) И он кругом определенный? Т.е. Справочник.ТМЦ а не Справочник ?
|
|||
47
DarkFrenzy
29.11.10
✎
15:18
|
(46) Для всех Справочник.Номенклатура
|
|||
48
Mikeware
29.11.10
✎
15:32
|
(47) во-первых, то, что реквизит с именем "Номенклатура" содержит данные вида "Справочник.номенклатура" - всего лишть соглашение, и не более. А соглашениям верить нельзя. Поэтому - проверяй тип.
Во-вторых, есть еще реквизиты - справочники неопределенного вида. Или даже вообще неопределенного типа... Это тоже учитывай |
|||
49
Злой Бобр
29.11.10
✎
15:53
|
(48) Согласен на все 100. Но если автору нужно побыстрячку слепить, то вероятно пока на это можно закрыть глаза. Хотя конечно же нет ничего более постоянного чем временное, поэтому лучше сразу писать по уму.
|
|||
50
DarkFrenzy
29.11.10
✎
16:18
|
(47), (48) Да я тоже с вами согласен, просто на данный момент у реквизита "номенклатура" всех видов документов такой тип.
Побыстрячку лепить не надо, для этого уже есть обработка с простым перебором. Сейчас цель - правильно составить 1Сный запрос:) Изучение 1sqlite/MSSQL все же оставлю на потом, когда нормально изучу 1с |
|||
51
palpetrovich
29.11.10
✎
17:36
|
(50) можешь на потом, а можешь и попробовать нижеизложенную поделку :)
зы: мне самому интересно, только разбираюсь с 1sqlite. Спасибо Eprst-у за помощь... в общем - то что получилось. Работает! //========================================================= Функция ПолучитьСписокДоков(ИмяРеквизита) Перем Реквизит; СписокДоков.УдалитьВсе(); Для Индекс=1 По Метаданные.Документ() Цикл ВидДокумента = Метаданные.Документ(Индекс).Идентификатор; Реквизит=Метаданные.Документ(ВидДокумента).РеквизитТабличнойЧасти(ИмяРеквизита); Если Реквизит.Выбран()=1 Тогда СписокДоков.ДобавитьЗначение(ВидДокумента, Реквизит.Вид); КонецЕсли; КонецЦикла; Возврат СписокДоков; КонецФункции //========================================================= Процедура ПолучитьДокиСНоменклатурой() ПолучитьСписокДоков("ТМЦ"); базаДанных.Открыть(":memory:"); Запрос = базаДанных.НовыйЗапрос(); запрос.ВыполнитьЗапрос("PRAGMA journal_mode = WAL"); РеквизитВид = ""; ТекВид = СписокДоков.ПолучитьЗначение(1, РеквизитВид); Если РеквизитВид<>"" Тогда РеквизитВид = "." + РеквизитВид; КонецЕсли; текст=" |Select | Таб.Документ [Док :Документ], | Таб.Товар [Товар :Справочник] |From |( | SELECT | :ВидДокумента."+ТекВид+"||Док.iddoc Документ,"; Если РеквизитВид="" Тогда текст=текст+" | Док.ТМЦ Товар"; Иначе текст=текст+" | :ВидСправочника.ТМЦ||Док.ТМЦ Товар"; КонецЕсли; текст=текст+" | FROM [DocumentLines."+ТекВид+"] Док"; Если ВыбрТМЦ.Выбран()=1 Тогда текст=текст+" | WHERE Док.ТМЦ = @ВыбрТовар"; КонецЕсли; Для инд=2 По СписокДоков.РазмерСписка() Цикл РеквизитВид = ""; ТекВид = СписокДоков.ПолучитьЗначение(инд, РеквизитВид); Если РеквизитВид<>"" Тогда РеквизитВид = "." + РеквизитВид; КонецЕсли; текст=текст+" |UNION ALL | SELECT | :ВидДокумента."+ТекВид+"||Док.iddoc,"; Если РеквизитВид="" Тогда текст=текст+" | Док.ТМЦ"; Иначе текст=текст+" | :ВидСправочника.ТМЦ||Док.ТМЦ"; КонецЕсли; текст=текст+" | FROM [DocumentLines."+ТекВид+"] Док"; Если ВыбрТМЦ.Выбран()=1 Тогда текст=текст+" | WHERE Док.ТМЦ = @ВыбрТовар"; КонецЕсли; текст=текст+" |"; КонецЦикла; текст= текст + " |) Таб |"; Запрос.Подготовить(текст); Если ВыбрТМЦ.Выбран()=1 Тогда запрос.УстановитьПараметр("@ВыбрТовар", ВыбрТМЦ); КонецЕсли; Попытка тз=запрос.Выполнить(); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; тз.ВыбратьСтроку(); КонецПроцедуры |
|||
52
palpetrovich
29.11.10
✎
17:38
|
+51: только если будешь пробовать - наверняка тебе прийдется поменять "ТМЦ" на "Номенклатура". Может еще что...
ВыбрТМЦ - реквизит на форме СписокДоков - я получал просто все, где есть в табЧасти "ТМЦ". Ты можешь - как хочешь :) |
|||
53
palpetrovich
30.11.10
✎
15:00
|
малехо приведенный к чуть более нормальному виду:
Функция ПолучитьСписокДоков(ИмяРеквизита) Перем Реквизит; СписокДоков.УдалитьВсе(); Для Индекс=1 По Метаданные.Документ() Цикл ВидДокумента = Метаданные.Документ(Индекс).Идентификатор; Реквизит=Метаданные.Документ(ВидДокумента).РеквизитТабличнойЧасти(ИмяРеквизита); Если Реквизит.Выбран()=1 Тогда Если Реквизит.Вид="" Тогда СписокДоков.ДобавитьЗначение(ВидДокумента, ""); Иначе СписокДоков.ДобавитьЗначение(ВидДокумента, ":ВидСправочника."+Реквизит.Вид+"||"); КонецЕсли; КонецЕсли; КонецЦикла; Возврат СписокДоков; КонецФункции Процедура ОтборНоменклатурыСРазныхВидовДоков() ПолучитьСписокДоков("ТМЦ"); базаДанных.Открыть(":memory:"); базаДанных.УложитьОбъекты(ВыбрТМЦ,"ВыбрТовар",0,"ТМЦ"); Запрос = базаДанных.НовыйЗапрос(); запрос.ВыполнитьЗапрос("PRAGMA journal_mode = OFF"); РеквизитВид = ""; ТекВид = СписокДоков.ПолучитьЗначение(1, РеквизитВид); текст=" |Select | Таб.Документ [Док :Документ], | Таб.Товар [Товар :Справочник] |From |( | SELECT | :ВидДокумента."+ТекВид+"||Док.iddoc Документ, | " + РеквизитВид + "Док.ТМЦ Товар | FROM [DocumentLines."+ТекВид+"] Док | WHERE Док.ТМЦ in (select val from ВыбрТовар)"; Для инд=2 По СписокДоков.РазмерСписка() Цикл РеквизитВид = ""; ТекВид = СписокДоков.ПолучитьЗначение(инд, РеквизитВид); текст=текст+" |UNION ALL | SELECT | :ВидДокумента."+ТекВид+"||Док.iddoc, | " + РеквизитВид + "Док.ТМЦ | FROM [DocumentLines."+ТекВид+"] Док | WHERE Док.ТМЦ in (select val from ВыбрТовар)"; КонецЦикла; текст= текст + " |) Таб"; Запрос.Подготовить(текст); Попытка тз=запрос.Выполнить(); Исключение Сообщить(ОписаниеОшибки()); КонецПопытки; КонецПроцедуры |
|||
54
DarkFrenzy
30.11.10
✎
16:32
|
Подредактировал сегодня твой код для своей обработки ("ВыбрТМЦ" поменял везде на "ВыбТМЦ", а "ТМЦ" на "Номенклатура", добавил СписокДоков=СоздатьОбъект("СписокЗначений") и попытку базаДанных = СоздатьОбъект("SQLiteBase") как в примере (39)). Выдается ошибка -
"Значение не представляет агрегатный объект (ВыбратьСтроку)" на строку тз.ВыбратьСтроку(); Извращался по разному с кодом, но сделать запрос рабочим пока что не получается. Также, насколько я понял из кода, ВыбрТМЦ не проверяется на группу, содержащую элементы табличной части. Буду рад любой помощи. |
|||
55
DarkFrenzy
30.11.10
✎
16:34
|
Это про (51) было, (53) сейчас только увидел, завтра заценю:)
|
|||
56
palpetrovich
30.11.10
✎
16:42
|
(54) добавь вверху модуля
Перем базаДанных, СписокДоков; //и Процедура ПриОткрытии() Попытка базаДанных = СоздатьОбъект("SQLiteBase"); Исключение ЗагрузитьВнешнююКомпоненту("1sqlite.dll"); базаДанных = СоздатьОбъект("SQLiteBase"); КонецПопытки; СписокДоков = СоздатьОбъект("СписокЗначений"); КонецПроцедуры и "поменял на "Номенклатура"" - это если у тебя справочник действительно "Номенклатура" :) |
|||
57
palpetrovich
30.11.10
✎
16:55
|
+56 засвети мыло
|
|||
58
DarkFrenzy
01.12.10
✎
09:18
|
Да, номенклатура. darkbasic@mail.ru
|
|||
59
palpetrovich
01.12.10
✎
10:19
|
(58) проверь почту
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |