Имя: Пароль:
1C
1C 7.7
v7: использование в запросе условия на сравнение строки содержащей символ "
0 andrewch60
 
09.02.23
04:19
Необходимо запросом выбрать из большого справочника элементы по наименованию
список наименований может исчисляться сотнями.
хотел сразу сделать через условие наименование В Список значений, но забыл, что "лампа" войдет и в "лампа 60w"
пытаюсь сделать через склеивание в цикле Условия через сравнение на равенство и столкнулся с проблемкой, что в наименованиях содержится символ "
забыл, как с этим бороться
ТекстЗапроса =
    "//{{ЗАПРОС(Материалы)
    |Без итогов;
    |Наименование = Справочник.Материалы.Наименование;
    |ЕдиницаИзмерения = Справочник.Материалы.ЕдиницаИзмерения;
    |Цена = Справочник.Материалы.Цена;
    |СтранаПроисхождения = Справочник.Материалы.СтранаПроисхождения;
    |Материал = Справочник.Материалы.ТекущийЭлемент;
    |Группировка Наименование без групп;  
    |Группировка Цена без групп;
    |"//}}ЗАПРОС
    ;

        СтрУсловия = "";
    Для н=1 По РазмерСпискаН Цикл
        Стр = "";
        СтрУсловия = СтрУсловия + " ИЛИ (СокрП(Наименование) = """""+ СтрЗаменить(СписокНаименований.ПолучитьЗначение(н, Стр), """","""""""""") + """"")" + РазделительСтрок;
    КонецЦикла;
        ТекстЗапроса = ТекстЗапроса + "Условие(" + Сред(СтрУсловия, 6) + ");";

получаю ошибку :  ИЛИ (СокрП(Наименование) = "Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло " <<?>> "Кольца""/прямое основание) TDM")
Запрос[114] : Ожидается ')' перед '"Кольца"'

вывод текста запроса перед исполнением :
//{{ЗАПРОС(Материалы)
Без итогов;
Наименование = Справочник.Материалы.Наименование;
ЕдиницаИзмерения = Справочник.Материалы.ЕдиницаИзмерения;
Цена = Справочник.Материалы.Цена;
СтранаПроисхождения = Справочник.Материалы.СтранаПроисхождения;
Материал = Справочник.Материалы.ТекущийЭлемент;
Группировка Наименование без групп;  
Группировка Цена без групп;
Условие((СокрП(Наименование) = "Лампа Navigator 82 462 NLLB-A60-10-230-6.5K-E27")
ИЛИ (СокрП(Наименование) = "Лампа Navigator 82 463 NLLB-A60-12-230-6.5K-E27")
ИЛИ (СокрП(Наименование) = "Лампа Navigator 82 506 NLLB-C37-7-230-4K-E14-FR")
ИЛИ (СокрП(Наименование) = "ATN000501 ATLASDESIGN 1-постовая РАМКА, ШАМПАНЬ")
...
ИЛИ (СокрП(Наименование) = "Светильник SQ0314-0002 НББ64-60-025 УХЛ4 (шар пластик/наклонное основание) TDM")
ИЛИ (СокрП(Наименование) = "Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло ""Кольца""/прямое основание) TDM")
ИЛИ (СокрП(Наименование) = "ATN000583 ATLASDESIGN РОЗЕТКА компьютерная RJ45, механизм, ШАМПАНЬ")
);
1 Irbis
 
09.02.23
06:14
""
2 NorthWind
 
09.02.23
06:57
Насколько я помню, в запрос же можно передать контейнер (массив, ТЗ) в качестве параметра. Так сложите туда ваши наименования, и всех делов ...
3 NorthWind
 
09.02.23
07:07
В семерке, точно помню, передавался СписокЗначений...
4 Злопчинский
 
09.02.23
07:36
"Необходимо запросом выбрать из большого справочника элементы по наименованию"
группировки убрать вообще. для выборки элементов справочника они не нужны, тем более нет агрегирующих функций.
.
Условие(СписокНаименований.НайтиЗначение(СокрП(Наименование))<>0);
5 Злопчинский
 
09.02.23
07:38
Ну и в списокНаименований загонять не строки, а нужные текущие элементы спр.материалы и
Условие(СЗМатериалы.НайтиЗначение(Материал)<>0);
6 Злопчинский
 
09.02.23
07:39
к (5): если есть такая возможность
7 Злопчинский
 
09.02.23
07:44
а не проще СРАЗУ искать по наименованиям?
Цикл ДанныеОТкудаТо
  НаименованиеВнешнее = ПолучитьНаименование();
  Результат = СпрМатериалы.НайтиПоНаименованию(НаименованиеВнешнее);
  Если Результат = 0 Тогда Продолжить; КонецЕсли;
  Материал = СпрМатериалы.ТекущийЭлемент(); // делаем что надо с найденным материалом
  ....
КонецЦикла;
8 АгентБезопасной Нацио
 
09.02.23
08:02
Еще одна угнанная учетка...
9 Злопчинский
 
09.02.23
08:05
(8) не, просто народ возвращается от богомерзких поделий к православным клюшкам... ;-)
10 АгентБезопасной Нацио
 
09.02.23
08:27
(9) его страна обитания, такое ощущение, что и не уходила.
там все клюшечники, и один другого краше...
впрочем, судя по темам, он 10 лет на клюшках...
11 NorthWind
 
09.02.23
08:48
(5) А почему не

Условие (Материал В СЗМатериалы);

?
12 Irbis
 
09.02.23
08:56
(11) Там вариантов реализации тьма, от в списке и загрузки в отдельный подзапрос ТЗ до ПОДОБНО и подстрока подобия. Чтобы советовать, похоже нужно знать реальную задачу.
13 andrewch60
 
09.02.23
13:56
Не касался 7ки почти лет 8
Может я плохо описал ситуацию
Попросили сделать загрузку ТЧ ПоступленийМатериалов от одной организации из DBF файла. Он содержит Наименование и цену.
Справочник Материалов большой, партионного учета нет. Т е один материал по новой цене вносится новым элементом. Не факт, что и с одинаковой ценой не вносили дубли
Решил, что в цикле по каждой строке ТЧ из ДБФ искать по наименованию и цене материалы будет долго.
свернул таблицу по Наименованию  и по Цене, выгрузил список Наименований и список Цен
Попробовал Условие (Наименование В СписокНаименований); Условие (Цена В СписокЦен);
Посмотрел, что элементы справочника с наименованиями "лампа", "лампа Navigator", "лампа Navigator 82" попадут в выборку при сравнении с "Лампа Navigator 82 463 NLLB-A60-12-230-6.5K-E27"
Т е сравнение идет на частичное совпадение, что не подходит.
НайтиПоНаименованию тоже не катит - он найдет первый элемент с таким наименованием, а их может быть много
14 andrewch60
 
09.02.23
13:59
(1) СтрЗаменить(СписокНаименований.ПолучитьЗначение(н, Стр), """","""""""""") у меня и удваивает " внутри наименования:
из Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло "Кольца"/прямое основание) TDM получаю "Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло ""Кольца""/прямое основание) TDM"

ИЛИ (СокрП(Наименование) = "Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло ""Кольца""/прямое основание) TDM")
15 Irbis
 
09.02.23
14:07
Плохо клюшки помню, но для объектов там было что-то типа .Выбрать() с параметрами типа выбрать по реквизиту.
16 andrewch60
 
09.02.23
14:13
(15) Да, только у этого реквизита должна быть галка "Отбор по реквизиту"(тогда вроде отдельный индекс создавался по нему) и Наименование туда не входит
не хочу изменять конфигурацию, и в любом случае запрос должен намного быстрее отработать, если эту проблемку с кавычкой решить. И помнится, что она как то решаема...
кстати ПОДОБНО и подзапрос с параметром ТЗ вроде только в 8ке... но не уверен
17 АгентБезопасной Нацио
 
09.02.23
14:28
как соотносятся названия в файле, цены, и названия материалов?
18 Irbis
 
09.02.23
14:28
(16) >> кстати ПОДОБНО и подзапрос с параметром ТЗ вроде только в 8ке... но не уверен
Да это я плохо посмотрел на раздел
19 Irbis
 
09.02.23
14:30
СтрЗаменить(СписокНаименований.ПолучитьЗначение(н, Стр), """","""""""""") зачем в заменяемой подстроке столько "? По смыслу задачи должно быть ровно 6
20 АгентБезопасной Нацио
 
09.02.23
14:31
(16) черный запрос быстрее не отработает. Он отбирает по ключу, если возможно, и тянет на клиента dbf (результат первичной выборки),  в котором уже с клиента локально ищет (за давностью лет, не помню, как индексирует)
Поставь 1sqlite
21 Irbis
 
09.02.23
14:31
Или вообще воспользоваться поиском и генерацией символа по коду в таблице кодов
22 АгентБезопасной Нацио
 
09.02.23
14:32
+(20) если, конечно, база файловая. а если не файловая, то вообще лепота.
23 andrewch60
 
09.02.23
14:46
(17) полное совпадение наименования и цены. иначе создаем новый элемент
24 andrewch60
 
09.02.23
14:48
(19) ночью уже сколько не пробовал ... в текущей версии глянул - 6. результат - ошибка та же
25 andrewch60
 
09.02.23
14:48
(24) СтрУсловия = СтрУсловия + " ИЛИ (СокрП(Наименование) = """+ СтрЗаменить(СписокНаименований.ПолучитьЗначение(н, Стр), """","""""") + """)" + РазделительСтрок;
26 Fedor-1971
 
09.02.23
14:49
(23) В таком раскладе: Условие(Наименование В СписокНаименований);
Список наименований запихиваешь в СписокЗначений
27 Irbis
 
09.02.23
14:50
Проверь визуально получившуюся строку в отладчике. Чудес на свете не бывает. Я бы вообще сначала собрал бы строку, а потом один раз заменил " на ""
28 Fedor-1971
 
09.02.23
14:50
26+ тогда без разницы есть ли в наименовании ", иначе придётся удвоить все "
29 andrewch60
 
09.02.23
14:53
(20) один раз запросом выбрать и потом уже цикл по отбору по цене очень вряд ли будет работать медленнее, чем поиск в цикле по всему справочнику. Кстати поиск по наименованию(как писал выше) только первый элемент вернет... Т е мне не подходит
30 Fedor-1971
 
09.02.23
14:56
(27) не факт, что анализ текста запроса не провалится в ошибку
(29) Попробуй ВыбратьЭлементыПоРеквизиту,  а потом цикл по ПолучитьЭлемент()
31 andrewch60
 
09.02.23
14:57
(27) я в первом после вставлял вывод текста запроса перед исполнением :
вывод текста запроса перед исполнением :
//{{ЗАПРОС(Материалы)
Без итогов;
Наименование = Справочник.Материалы.Наименование;
ЕдиницаИзмерения = Справочник.Материалы.ЕдиницаИзмерения;
Цена = Справочник.Материалы.Цена;
СтранаПроисхождения = Справочник.Материалы.СтранаПроисхождения;
Материал = Справочник.Материалы.ТекущийЭлемент;
Группировка Наименование без групп;  
Группировка Цена без групп;
Условие((СокрП(Наименование) = "Лампа Navigator 82 462 NLLB-A60-10-230-6.5K-E27")
ИЛИ (СокрП(Наименование) = "Лампа Navigator 82 463 NLLB-A60-12-230-6.5K-E27")
ИЛИ (СокрП(Наименование) = "Лампа Navigator 82 506 NLLB-C37-7-230-4K-E14-FR")
ИЛИ (СокрП(Наименование) = "ATN000501 ATLASDESIGN 1-постовая РАМКА, ШАМПАНЬ")
...
ИЛИ (СокрП(Наименование) = "Светильник SQ0314-0002 НББ64-60-025 УХЛ4 (шар пластик/наклонное основание) TDM")
ИЛИ (СокрП(Наименование) = "Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло ""Кольца""/прямое основание) TDM")
ИЛИ (СокрП(Наименование) = "ATN000583 ATLASDESIGN РОЗЕТКА компьютерная RJ45, механизм, ШАМПАНЬ")
);


вроде как выглядит красиво... " в наименовании заменилось на ""
кажется, что какую то дикую мелочь упускаю
32 andrewch60
 
09.02.23
15:00
(30) ВыбратьЭлементыПоРеквизиту с Наименованием не работает
33 Irbis
 
09.02.23
15:00
В визуальном контроле ""Кольца"" не должно быть
34 andrewch60
 
09.02.23
15:04
(33) допустим , что нам нужно только одно сравнение на = Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло "Кольца"/прямое основание) TDM
как должен выглядеть текст запроса (переменную использовать нельзя)?
35 Irbis
 
09.02.23
15:07
При визуальном контроле в отладчике примерно так:
= "Светильник SQ0314-0005 НББ64-60-025 УХЛ4 (шар стекло "Кольца"/прямое основание) TDM"
Двойная кавычка в строке наименования нужна чтобы корректно строка отображалась, визуально такого не должно наблюдаться
36 Builder
 
09.02.23
15:33
(18) Ну в клюшках черные запросы умеют искать подстроку в строке через В.
37 Злопчинский
 
09.02.23
15:56
че вы морочитесь?
делайте проще, это ж не каждые 5 секунд загрузка будет вертеться

//*******************************************
Процедура Сформировать()
ТекстЗапроса = "
|Без итогов;
|Наименование = Справочник.Номенклатура.Наименование;
|ЕдиницаИзмерения = Справочник.Номенклатура.БазоваяЕдиница;
|Цена = Справочник.Номенклатура.МинОстаток;
|Номенклатура = Справочник.Номенклатура.ТекущийЭлемент;
|Группировка Наименование;
|Группировка Цена;
|Условие(СписокНаименований.НайтиЗначение(СокрП(Наименование))<>0);
//|Условие(МояФункция(Наименование,Цена)=1);
|";//}}ЗАПРОС    
    
Запрос = СоздатьОбъект("Запрос");
Запрос.Выполнить(ТекстЗапроса);
ТЗ = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТЗ,1,0);
//ПечатьТЗ(ТЗ);

ТЗ.НоваяКолонка("Ключ","Строка");
Цикл по ТЗ
    ТЗ.Ключ = ТЗ.Наименование+"^"+ТЗ.Цена; // РЕГИСТР НАИМЕНОВАНИЯ и ФОРМАТ ЦЕНЫ!!!! СОБЛЮАДСТЬ!!!
КонецЦикла;

Цикл по данным ДБФ
    КлючДБФ = ДБФ.Наименование+разделитель+ДБФЦена.
    ТЗ.НайтиЗначение(КлючДБФ,поз,"Ключ");
КонецЦикла

КонецПроцедуры
38 Злопчинский
 
09.02.23
15:58
Можно прочитать данные из ДБФ, сформировать ключ ДБФ, загнать эти ключи в СЗ (глобальный для обработки)
а в запросе в МояФункция() делать
Функция МояФункция(Наименование,Цена)
  Ключ = Наименование+Цена;
  поз = СЗключейДБФ.НайтиЗначение(Ключ);
  Возврат ?(поз=0,0,1);
КонецФункции
39 Злопчинский
 
09.02.23
15:59
тогда запрос вернет строки подходящие только по наименованию и цене
дальше с этой выборкой (ТЗ результата запроса) - что хошь то и делай
40 Злопчинский
 
09.02.23
15:59
развели бодягу на неделю...
41 andrewch60
 
09.02.23
17:57
(37) |Условие(СписокНаименований.НайтиЗначение(СокрП(Наименование))<>0);
так работает, спасибо

хотя не пойму, почему такой запрос не получается сделать рабочим...
ТекстЗапроса =
    "
    |Без итогов;
    |Наименование = Справочник.Материалы.Наименование;
    |ЕдиницаИзмерения = Справочник.Материалы.ЕдиницаИзмерения;
    |Цена = Справочник.Материалы.Цена;
    |СтранаПроисхождения = Справочник.Материалы.СтранаПроисхождения;
    |Материал = Справочник.Материалы.ТекущийЭлемент;
    |Группировка Наименование без групп;  
    |Группировка Цена без групп;
    |Условие(СокрЛП(Наименование) = ""Светильник"""" TDM"");";
42 Chai Nic
 
09.02.23
18:04
Когда в далеком 2000 году я проходил курсы конфигурирования в 1с 7.7, сертифицированный 1совский препод по секрету сказал, что запрос это самый неудачный механизм платформы и им пользоваться не надо. Уже тогда.
С тех пор прошло много лет. Появились 1с++ с прямыми SQL запросами, которые работают предсказуемо быстро.
Но люди почему-то до сих пор занимаются ерундой и тратят время на "черные запросы", которые мало того что неочевидны, так ещё и непредсказуемы по скорости. Например, запрос может половину базы забрать в каталог временных файлов а потом в этой куче ковыряться, хрустя диском.
43 Злопчинский
 
09.02.23
18:55
(41) "хотя не пойму, почему..."
1. потому что идея в условие пихать сравнение кучи строк - мудачная.
2. потому что итоговая строка условия тебя выглядит так
Условие(СокрП(Наименование) = "Светильник"" TDM");

напиши в виде литерала БЕЗ синтаксических ограничивающих кавычек только с внутренними кавчками в наименовании как у тебя этот светильник ТДМ называется
44 Злопчинский
 
09.02.23
19:27
.. но запихнуть в литерал для сравнения наименование
Светильник "TDM"
у меня не получилось...
45 andrewch60
 
09.02.23
20:04
(43) 1 идея может и хреновая, если есть другая хорошая...
2 именно так и выглядит итоговая строка (для простоты оставил одно условие на Светильник "TDM )  всего одно сравнение, всего одна кавычка... а запрос так и не работает...
46 andrewch60
 
09.02.23
20:05
теперь уже не для решения моей задачи, запрос с кучей ИЛИ и без кавычек работает крайне медленно
но любопытства ради
47 andrewch60
 
09.02.23
20:07
(4) без группировок 7ка вроде как ничего не выбирает вообще...
48 Злопчинский
 
09.02.23
20:28
(47) да, ошибся. это я с прямым углом попутал...
49 Злопчинский
 
09.02.23
20:29
(45) Условие(СписокНаименований.НайтиЗначение(СокрП(Наименование))<>0);
и не мучай себе мозги. с кавычками в наименовании мне не удалось добиться чтобы запрос не ругался..
50 Злопчинский
 
09.02.23
20:30
(46) по сути запрос тупо перебирает все записи и начинает сравнивать с литералами. Сравнение строк всегда медленно.
51 Злопчинский
 
09.02.23
20:31
(35) мне кавычки внутри наименования не удалось победить.
52 andrewch60
 
09.02.23
20:35
(50) и через список без сравнения строк никак не может обойтись... но пути господни неисповедимы)
53 Злопчинский
 
09.02.23
20:36
Можно вообще без запроса сделать и будет еще быстрее...
типа

попробовать

прочитали запись с ДБФ.
НаименованиеДБФ

СпрМ.ПорядокНаименований();
СпрМ.ВыбратьЭлементы();
СпрМ.НайтиПоНаименованию(НаименованиеДБФ); // тут тупо сдвинули выборку не в начало а куда-то в середину - МОЖЕТ ПРОКАТИТ
Пока СпрМ.ПолучитьЭлемент()=1 Цикл
  Если СпрМ.Наименование <> НаименованиеДБФ Тогда Прервать; КонецЕсли;
  // а тут делаем что надо
54 Злопчинский
 
09.02.23
20:37
(52) ну потому что пихать для обмена в качестве ключа доступа/синхронизации в ДБA наименование - так себе идея? но вполне рабоачая.
а то что у вас туева хуча дублей материалов (которые все "ломают") - ССЗБ
55 Злопчинский
 
09.02.23
20:37
(53) ща попробую тестовый накидать
56 Злопчинский
 
09.02.23
20:51
(55) не.. так не пойдет, выборка рушится
57 Злопчинский
 
09.02.23
21:00
(52) ну а как ты хочешь, если во внешнем файле у тебя ключ синхронизации - длинная строка, не гуид какой-нить.
58 andrewch60
 
09.02.23
21:00
(55) не мучайтесь, запрос с Условие(СписокНаименований.НайтиЗначение(СокрП(Наименование))>0);  отрабатывает меньше чем за 1 сек. Совпадений почему то почти нет... Более чем приемлемо  
Больше не вижу проблемы
спасибо
единственное : раньше пользовался OpenConf а сейчас почему то :
Не могу создать объект OpenConf.CommonServices
Скрипт Intellisence не загружен
Не могу создать объект OpenConf.CommonServices
Скрипт Форматирование текста не загружен
...
а ,помнится, было очень удобно
может подскажете, где взять последнюю версию?
59 Злопчинский
 
09.02.23
21:01
(58) ну и ок.
60 Злопчинский
 
09.02.23
21:03
(58) "Совпадений почему то почти нет..."
а тут тебе не регистронезависимый индекс.
надо соблюдать совпадение регистров. один лишний пробел/запт/слэш/или чтонить - и всё, совпадения не будет...
то есть если в СЗ будет "ЧТОТО", а ты ищешь "Чтото" - то результат =0
61 Злопчинский
 
09.02.23
21:04
(58) OpenConf Light Pack на ИС и поправки к нему для х64
и на ИС сборки скриптов 1-2 публикации есть
а так - наверное на форуме 1С++
62 Злопчинский
 
09.02.23
21:06
(60) т.е. в СписокНаименований я бы совал НРег(СокрЛП(НаименованиеВнешнее))
а в услвоии сооответсвоенно НРег(СокрЛП(Наименование))
63 andrewch60
 
09.02.23
21:22
(60) за это отдельное спасибо, не пришло в голову
с запт/слэш/или чтонить ничего не поделаешь, а вот с регистром - да
64 Злопчинский
 
09.02.23
22:16
(63) ну и с небуквенными символами тоже можно без проблем (быстродействие только)
перед тем как совать НаименованиеВнешнее в СЗ - нормализуй его, типа

//*****************************************************************
//заменяет в строке Источник символы из набора НормальныйШаблон
//на символ Нормализатор;
//если в наборе НормальныйШаблон присутствует символ Нормализатора,
//то нормализация происходит на пустой символ
//
Функция глНормализоватьСтроку(Знач Источник, Знач НормальныйШаблон="\/:*?""<>| ", Знач Нормализатор="#") Экспорт
    Если Найти(НормальныйШаблон,Нормализатор)<>0 Тогда Нормализатор = ""; КонецЕсли;
    Источник = СокрЛП(Источник);
    Дл = СтрДлина(НормальныйШаблон); Для ы=1 по Дл Цикл Источник = СтрЗаменить(Источник,Сред(НормальныйШаблон,ы,1),Нормализатор); КонецЦикла;
    Возврат Источник;
КонецФункции //глНормализоватьСтроку()


    НаименованиеВнешнее = глНормализоватьСтроку(НаименованиеВнешнее,НормальныйШаблон,"");
    НормальныйШаблон = "-–№”""«»,\/:*?<>|!#() "+РазделительСтрок+СимволТабуляции+Симв(9)+Симв(160); //сюда еще можно добавить всякой хрени все нефонетические символы

а в условии используй МояФункция, в которую передавай Наименование из запроса ив функции наименование из запроса тоже нормализуй вызовом той же самой глНормализоватьСтроку и только потом найтизначение - нормализованное из запроса среди нормализованных из внешнего источника
Ошибка? Это не ошибка, это системная функция.