Только ленивый, по-моему, не писал еще о вариантах вырезания гланд через анус автогеном запросами. Ну и я поделюсь.
К сожалению, возможности запросов 1С в отношении строковых переменных крайне малы. Практически они исчерпываются одной функцией и одним оператором. Тем не менее, постоянно всплывают темы в духе «а как мне сделать это прямо в запросе?». Конечно, большинство задач решаются в СКД, оставшаяся часть решается пост-обработкой результата, но чисто в качестве разминки для ума, кое-что в запросе сделать можно.
Во всех примерах я буду использовать следующие временные таблицы:
ВЫБРАТЬ
«_» КАК Симв,
1 КАК КолСимв
ПОМЕСТИТЬ тзКоличествоСимволов9
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«__»,
2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«___»,
3
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«____»,
4
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«_____»,
5
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«______»,
6
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«_______»,
7
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«________»,
8
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«_________»,
9
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
«»,
0
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Лев.Симв + тзКоличествоСимволов9_Прав.Симв КАК Симв,
тзКоличествоСимволов9_Лев.КолСимв * 10 + тзКоличествоСимволов9_Прав.КолСимв КАК КолСимв
ПОМЕСТИТЬ тзКоличествоСимволов100
ИЗ
тзКоличествоСимволов9 КАК тзКоличествоСимволов9_Лев,
тзКоличествоСимволов9 КАК тзКоличествоСимволов9_Прав
;
////////////////////////////////////////////////////////////////////////////////
Для приведенных примеров их вполне хватит, смысл, думаю, понятен, так что не будем заострять внимание на оптимальности их построения.
Так же рекомендую экспериментировать с приведенными запросами в файловых базах – серверные более нежные и работать автогеном в таком грязном месте не любят. 🙂
- Подсчет количества символов в строке.
Тут всё очень просто
ВЫБРАТЬ
Номенклатура.Наименование,
КоличествоСимволов.КолСимв
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволов
ПО (Номенклатура.Наименование ПОДОБНО КоличествоСимволов.Симв)
Всё. Теперь можно отрезать последний пробел, например:
ВЫБРАТЬ
Номенклатура.Наименование,
КоличествоСимволов.КолСимв,
ВЫБОР
КОГДА Наименование подобно «% «
ТОГДА ПОДСТРОКА(Номенклатура.Наименование, 1, КоличествоСимволов.КолСимв — 1)
ИНАЧЕ Номенклатура.Наименование
КОНЕЦ КАК НаименованиеБезПробела
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволов
ПО (Номенклатура.Наименование ПОДОБНО КоличествоСимволов.Симв)
2. Разбить строку
Здесь чуть сложнее. Но теми же граблями.
Задача: в некоторой номенклатуре в наименовании записан некоторый текст в скобках. Надо вытащить этот текст в отдельное поле.
Для простоты договоримся, что скобочки в наименовании у нас один раз открываются и один раз закрываются.
ВЫБРАТЬ Различные
Номенклатура.Ссылка,
Выразить(ПОДСТРОКА(Номенклатура.Наименование, КоличествоСимволовДоОткрытия.КолСимв+2, КоличествоСимволовДоЗакрытия.КолСимв—КоличествоСимволовДоОткрытия.КолСимв—1) как строка(100)) КАК ТекстВСкобках
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоОткрытия
ПО (Номенклатура.Наименование ПОДОБНО КоличествоСимволовДоОткрытия.Симв + &СимволОткрытия + «%»)
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоЗакрытия
ПО (Номенклатура.Наименование ПОДОБНО КоличествоСимволовДоЗакрытия.Симв + &СимволЗакрытия + «%»)
ГДЕ
Номенклатура.Наименование ПОДОБНО «%» + &СимволОткрытия + «%» + &СимволЗакрытия + «%»
Тут &СимволОткрытия, понятно «(»,&СимволЗакрытия соответственно «)». Находим позицию символов и вытаскиваем подстроку. Помним, что запросы тошнит от строк неограниченной длины, поэтому используем ВЫРАЗИТЬ.
3. Сложное соединение по строке.
Ну и совсем извращение, но пример взят из реальной темы.
Существуют две таблицы:
В одной номера договоров в формате: «Номер-постфикс»
В другой номера тех же договоров, но дополненные неким доп-индексом в формате: «Номер/Индекс-постфикс».
Необходимо связать. Номер, индекс и постфикс могут быть разной длины, ориентироваться можно только на «/» и «-».
Сымитируем данные:
Выбрать
«30568-12» как ВнутреннийНомер
поместить тз1
Объединить все
Выбрать
«3568-12»
;
Выбрать
«30568/1-12» как ВнутреннийНомер
поместить тз2
Объединить все
Выбрать
«30568/155-12»
Объединить все
Выбрать
«30568/2-12»
Объединить все
Выбрать
«35681/2-12»
Объединить все
Выбрать
«3568/2-12»
Объединить все
Выбрать
«3568/2-13»
;
И начнем выпендриваться.
//Выделим из номеров те части, по которым сможем связывать
Выбрать
тз1сРазбиением.ВнутреннийНомер,
Подстрока(тз1сРазбиением.ВнутреннийНомер,1, КоличествоСимволовДоТире.КолСимв) как ДоСлэша,
Подстрока(тз1сРазбиением.ВнутреннийНомер,КоличествоСимволовДоТире.КолСимв+2, СтрДлина.КолСимв) как ПослеТире
поместить тз1сРазбиением
из тз1 как тз1сРазбиением
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоТире
ПО (тз1сРазбиением.ВнутреннийНомер ПОДОБНО КоличествоСимволовДоТире.Симв+«-%»)
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК СтрДлина
ПО (тз1сРазбиением.ВнутреннийНомер ПОДОБНО СтрДлина.Симв)
;
Выбрать
тз2сРазбиением.ВнутреннийНомер,
Подстрока(тз2сРазбиением.ВнутреннийНомер,1, КоличествоСимволовДоСлэша.КолСимв) как ДоСлэша,
Подстрока(тз2сРазбиением.ВнутреннийНомер,КоличествоСимволовДоТире.КолСимв+2, СтрДлина.КолСимв) как ПослеТире
поместить тз2сРазбиением
из тз2 как тз2сРазбиением
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоСлэша
ПО (тз2сРазбиением.ВнутреннийНомер ПОДОБНО КоличествоСимволовДоСлэша.Симв+«/%»)
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоТире
ПО (тз2сРазбиением.ВнутреннийНомер ПОДОБНО КоличествоСимволовДоТире.Симв+«-%»)
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК СтрДлина
ПО (тз2сРазбиением.ВнутреннийНомер ПОДОБНО СтрДлина.Симв)
;
ВЫБРАТЬ Различные
тз11.ВнутреннийНомер,
тз22.ВнутреннийНомер
ИЗ
тз1сРазбиением КАК тз11
Левое СОЕДИНЕНИЕ тз2сРазбиением КАК тз22
ПО тз11.ДоСлэша Подобно тз22.ДоСлэша
и тз11.ПослеТире Подобно тз22.ПослеТире
Для любителей возмущающаться напомню, что целью было отвлечься от работы J Если кому-то пригодится в практических целях, буду рада.




Временные таблицы со строками и куча ПОДОБНО ?
да это просто издевательство над скулем какое-то
определяем длину строки:
Показать
здесь выделяем из строки то, что в скобках:
Показать
3. Сложное соединение по строке.
Ну и совсем извращение,
действительно, извращение ))
собственно, делается по аналогии, тут уже лень
да, вот ещё в копилку: выбор строки с макс.длиной
Показать
здесь определяем последний (самый правый) символ строки и его позицию:
Показать
(2) По-русски сложно написать? Обязательно свои понты дешёвые показать.
(1)Ага 🙂
(2)На серверной базе моя длина строки работает в полтора раза быстрее(на справочнике 18000 элементов) На файловой в 7 раз(28 секунд против 4). 🙂 И пустые строки ваш запрос игнорирует, исключает из выборки как класс.
А в остальном да, скуль мои запросы не ест 🙂
Хотя на файловой мои все-таки быстрее )))
(7) Поручик, о чём Вы, сударь? какие понты? я всегда так пишу. а кто органически неприемлет английский и/или sql-ный синтаксис тех смиренно прошу мои посты игнорировать
(9) зато на серверных Ваши могут вообще упасть. вот за DB2, в частности, я очень не уверен, на этой СУБД 1с-вское ПОДОБНО зело глючит
(8) а пустые строки зачем обрабатывать? хотя, и это можно предусмотреть
(8) как замеры производили?
(11)Я и говорю, что падают. Хотя странно, оракл, например, вроде хорошо работает с like’ом.
Я не отрицаю, что намудрила, но вы же тоже не делитесь знаниями 🙂 Вот про скобки девушка летом вопрошала на форуме и ей в один голос заявили, что в запросе никак. Теперь хоть в поиске будет 🙂 Да и сложное соединение — реальный пример.
(12)Ну чтобы было. Для порядку. Эт я придираюсь.
(13)В консоли с «WINMM.DLL», «timeGetTime»
(15) если не забуду, сегодня на работе постараюсь сравнить время моих и Ваших запросов, отпишусь
лично я всегда делюсь, если встречаю. я эти строки в запросах долго крутил. даже где-то валяется текст по переводу дробного числа из текстового представления в числовое в запросе
Вот так сделал недавно:
Показать
(15) сразу не разглядел, но причина в том, что у меня макс.длина строки определяется в 1000, у Вас — всего в 100
если переопределить данную табличку
Показать
, то, естественно, получаются совершенно другие временные результаты
(18) kasper076, угу, а теперь попробуйте переписать для кода, скажем, длиной в 15 символов
Переписывание займет конечно какое-то время, но это нужно будет сделать всего 1 раз. Если прирост от данного метода будет ощутим, то выбор оправдан. Если нет, то конечно использовать постобработку результата запроса.
(19)Да действительно, я тоже не обратила на это внимания. Минус одно соединение.
Агрегатной функции конкатенации все-таки оченно не хватает.
(23) Вы не про это?
🙂
(22) как я и ожидал, Ваш вариант разбивки строки в DB2 не отрабатывает. а мой — отрабатывает 😉
чего только не придумают, и всё от того, что язык запросов в снеговике недоделан
:((
ЗЫ: про доп табличку с циферками, обычно есть куча примеров в любой книжке по sql..
(25)Я это еще утром признала.
(24)Не, я про группировки. Например, в оракле я могу так:
with Str as (
select
‘fff’ f1 from dual
union all
select
‘yyy’ from dual
union all
select
‘rrr’ from dual
)
select wmsys.wm_concat(Str.f1) from Str
(26) Ёпрст, угу, 1С — виновница очень многих извращений
(27) ну, в mssql тоже много чего можно, вплоть до итераций
(27) в sqllite тоже есть group by concat
а всё почему: потому, что
ПОДОБНО при использовании DB2
Проблема:
В клиент-серверном варианте работы, при использовании СУБД IBM DB2, в запросах, содержащих операцию ПОДОБНО и выражение (а не фиксированную строку) справа от операции, может происходить ошибка и сервер СУБД аварийно завершает свою работу.
Способы решения:
Использовать DB2 9.7 FixPack5
Дата публикации: 2012-04-10
причём, в фикспаке сервак просто не рушится, но результат пустой
да бог с ним, с конкатом. лично меня бы очень устроили хотя бы нормальные реализации cast’ов и коррелированных подзапросов
Извращенцы… 🙂
(28)Зато ничего не страшно 🙂 Когда мне понадобилось быстро научиться читать/писать простейшие оракловые запросы, я для тренировки переводила отрисовку календаря из какой-то местной статьи, а потом доводила до инфаркта получившимся кодом местных ораклистов 🙂
(7) Поручик, Я даже не сразу понял, что текст английский. Сначала забрасываю все в Консоль запросов, а там код преобразуется в русский на автомате. ))))
(26) В смысле строковых операций в запросе много где недоделано. Я вот не знаю, есть ли диалекты, понимающие регулярные выражения в запросе скуля, так что не надо обижать снеговика. С возвращением возможности втыкать общие функции в СКД уже очень много что можно, хотя и транслируется извратно.
Вообще не понимаю я, зачем такие грабли. Только из желания поковыряться ногой в носу, или есть-таки практическое применение? Имхо, грамотно организованные структуры данных и код алгоритмов никто не отменял.
(0) В итоге получаем нечитабельный запрос а’ля обфускация. К чему это? Смахивает на софистику т.е. игра словами ради игры. Думаю такие статьи должны сопровождаться знаком «Только для извращенцев которые все перепробовали». Если такие операции приводят к существенному увеличению производительности то конечно оно того стоит, но вроде об этом как то смутно сказано только в комментариях.
А как соединить в запросе строковое поле и поле даты?
Что-то такое:
ТекстЗапроса=
…..
Документ.Номер+» от «+Документ.Дата
….
Через Выразить, подстрока.. не получается.
Извините за вопрос, а какое объединение можно использовать в 1С? А то я слышала что в СКД как с объединениями ни крути — 1С всё переделает как левое внутреннее…
(38)На прямую — никак. Можно дату выразить как строку, тоже то еще извращение.
(39)В языке запросов можно использовать любые соединения. В СКД соединения между наборами данных осуществляются левыми соединениями, а в запросе так же можно организовать любое.
Подскажите мудрые 1С-ники как в запросе найти дубли номенклатуры у которых незначительно отличаются артикулы?
Например: Номенклатура 1 арт Х-1234
Номенклатура 2 арт Х-1233
Номенклатура 3 арт Х-1243
минимальная длина артикула, которая должна совпадать = 4
(41) OlenkaD, используйте ПОДОБНО
Получился такой запрос:
ВЫБРАТЬ
СвободныеОстаткиОстатки.Номенклатура,
СвободныеОстаткиОстатки.ВНаличииОстаток КАК ПоложитОстаток,
СвободныеОстаткиОстатки.Номенклатура.Артикул
ПОМЕСТИТЬ ПоложительныеОстатки
ИЗ
РегистрНакопления.СвободныеОстатки.Остатки(, Склад = &Склад) КАК СвободныеОстаткиОстатки
ГДЕ
СвободныеОстаткиОстатки.ВНаличииОстаток > 0
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
СвободныеОстаткиОстатки.Номенклатура,
СвободныеОстаткиОстатки.ВНаличииОстаток КАК ОтрицатОстаток,
СвободныеОстаткиОстатки.Номенклатура.Артикул
ПОМЕСТИТЬ ОтрицательныеОстатки
ИЗ
РегистрНакопления.СвободныеОстатки.Остатки(, Склад = &Склад) КАК СвободныеОстаткиОстатки
ГДЕ
СвободныеОстаткиОстатки.ВНаличииОстаток < 0
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
ПоложительныеОстатки.НоменклатураАртикул КАК АртикулПоложит,
ПоложительныеОстатки.Номенклатура КАК НоменклатураПоложит,
ПоложительныеОстатки.ПоложитОстаток,
ОтрицательныеОстатки.НоменклатураАртикул КАК АртикулОтрицат,
ОтрицательныеОстатки.Номенклатура КАК НоменклатураОтрицат,
ОтрицательныеОстатки.ОтрицатОстаток
ИЗ
ПоложительныеОстатки КАК ПоложительныеОстатки
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ОтрицательныеОстатки КАК ОтрицательныеОстатки
ПО (ПОДСТРОКА(ОтрицательныеОстатки.НоменклатураАртикул, 1, &Длина) ПОДОБНО ПОДСТРОКА(ПоложительныеОстатки.НоменклатураАртикул, 1, &Длина))
Теперь задача такая: параметр &Длина зависит от кол-ва символов в
ПоложительныеОстатки.Номенклатура КАК НоменклатураПоложит и может принимать значения от N (кол-во символов в этом поле) до &МинДлинаАртикула (которая заранее известна)
Как это можно реализовать в запросе?
Думается что то подобное написать:
Выбор когда ПоложительныеОстатки.НоменклатураАртикул = ОтрицательныеОстатки.НоменклатураАртикул Тогда
ОтрицательныеОстатки.НоменклатураАртикул
Иначе
Выбор когда
(ПОДСТРОКА(ОтрицательныеОстатки.НоменклатураАртикул, 1, &Длина) ПОДОБНО
ПОДСТРОКА(ПоложительныеОстатки.НоменклатураАртикул, 1, &Длина)) Тогда
ПОДСТРОКА(ОтрицательныеОстатки.НоменклатураАртикул, 1, &Длина)
Конец
Конец
Вопрос: как задавать параметр &Длина и считать длину строки прямо в запросе? (аналог СтрДлина)
Заморочилась так:
Когда Наименование = ПОДСТРОКА ( Наименование,1, 90) Тогда 90
Когда Наименование = ПОДСТРОКА ( Наименование,1, 91) Тогда 91
Когда Наименование = ПОДСТРОКА ( Наименование,1, 92) Тогда 92
Когда Наименование = ПОДСТРОКА ( Наименование,1, 93) Тогда 93
Когда Наименование = ПОДСТРОКА ( Наименование,1, 94) Тогда 94
Когда Наименование = ПОДСТРОКА ( Наименование,1, 95) Тогда 95
Когда Наименование = ПОДСТРОКА ( Наименование,1, 96) Тогда 96
Клуб извращенцов
(6) andrewks, (30) Ёпрст, а как посчитать длину строки в 1с 77 в прямом запросе,или хотя бы сравнить на равенство длины два значения
(47)А разве в прямых запросах недоступны функции скл?
(48) они доступны если база на скуле,а если dbf то синтаксис фокс про и там по своему это все.
(35) Зачетный лайфхак +1