Ссылка максимум в 1с какая выберется

Обновлено: 05.07.2024

Войдите как ученик, чтобы получить доступ к материалам школы

Язык запросов 1С 8.3 для начинающих программистов: объединение

Автор уроков и преподаватель школы: Владимир Милькин

Объединение в запросах

В языке запросов имеется возможность объединять несколько запросов. При этом записи, полученные с помощью каждого из объединяемых запросов, будут собраны в один результат запроса.

Как всегда начнём с примера.

Пусть требуется написать запрос, который возвращает все названия цветов и вкусов в одной таблице.

Цвета мы умеем выбирать так:

А вот, чтобы объединить эти два результата в один как раз и потребуется операция объединения:

Обратите внимание на то, что операция объединения вовсе не гарантирует, что элементы будут идти в каком-то определённом порядке. В общем случае они могут следовать друг за другом как угодно, поэтому если важен порядок необходимо как и всегда указывать его явно (через секцию УПОРЯДОЧИТЬ).

Требования к запросам, участвующим в объединении

У объединяемых запросов должно быть одинаковое количество полей . Иначе мы получим такую ошибку:

26

В объединяемых запросах соответствующие друг другу (по порядку) поля должны иметь одинаковый тип . Но это требование, в отличие от предыдущего, не является обязательным. Если соответствующие друг другу поля имеют разный тип, то поле результата будет иметь СОСТАВНОЙ тип, который разбирался нами на одном из прошлых уроков:

Несмотря на то, что поле первого запроса имеет тип СТРОКА, а второго ЧИСЛО, нам удалось объединить их в одну таблицу. Но тип результатирующего поля стал составным и нам придётся учитывать это в дальнейшем. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.

Кстати, вы заметили, что поле итоговой таблицы (после объединения) называется Наименование, а не Калорийность? Эта такое правило : поля итоговой таблицы всегда имеют названия совпадающие с именами описанными в первом из объединяемых запросов.

Объединение более двух запросов

При объединении каждый запрос собирает данные независимо, а уже затем результаты объединяются в один. Количество объединяемых запросов не ограничено.

Напишем объединение трёх запросов:

Повторяющиеся строки

Давайте объединим один и тот же запрос сам с собой:

Обратите внимание на то, что мы объединили две одинаковые таблицы цветов, а в результате каждый цвет встречается ровно один раз.

Всё потому, что по умолчанию при объединении запросов полностью одинаковые строки в результате запроса, заменяются одной. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.

Если требуется, чтобы были оставлены в том числе одинаковые строки (дубли), необходимо указать ключевое слово ВСЕ:

Упорядочивание при объединении

Пытаться отдельно упорядочивать результаты запросов, участвующих в объединении не имеет смысла. Поэтому при попытке написать:

31

Упорядочивать можно только результат объединения :

Обратите внимание на то, что секция УПОРЯДОЧИТЬ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.

Подведение итогов при объединении

Пытаться отдельно подводить итоги по запросам, участвующим в объединении, также не имеет смысла. Поэтому при попытке написать:

33

Подводить итоги можно только по результату объединения :

Обратите внимание на то, что секция ИТОГИ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.

Рабочий пример

Давайте решим такую задачу. Требуется вывести для каждого элемента справочника Еда закупленное и проданное количество за весь период.

Поступление еды у нас в базе происходит документом ПоступлениеЕды. У документа есть табличная часть Еда, с реквизитами Номенклатура и Количество.

Сначала выберем все строки табличной части Еда из всех поступлений:

Теперь сгруппируем этот результат по еде с суммированием количества:

Аналогичным образом получим продажу еды из документов ПродажаЕды:

Осталось объединить эти два запроса:

Обратите внимание на то, как мы дополнили оба запроса ещё одним полем СУММА(0). Мы вынуждены были сделать это, так как оба запроса содержат по два поля, а объединение запросов должно содержать три поля. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Если бы мы не сделали этого, а написали просто:

Протестировал эту реализацию, в конечный запрос не то что 1 строка, а целых две.

т.е. они оба так и остались:
Контрагент1 Пользователь1 Сотрудник1 2
Контрагент1 Пользователь2 Сотрудник2 2

а может действительно проще как (6) предложили? оставить записи со всеми подходящими сотрудниками, добавить сортировку по этим полям, чтобы был постоянный результат и выбирать первую запись (15) sommid, при тестировании со вложенным запросом получился результат такой, что пользователи стали нулами. Поэтому отказался от него. (5) Xershi, Максимум пользователя будет по ссылке или строке. Если не важно какой пользователь то да. (7) dj_serega, я так не хотел делать по той причине, что сегодня запустив запрос я получу одного пользователя, а через месяц другого (данные по количеству событий не будут меняться)? По большому счету это не особо важно, но хотелось бы чтобы ничего не менялось.

(7) максимум от ссылочного типа будет определятся по строке УИД этой ссылки,
для уже созданных справочников маловероятно, что будут менятся УИДы, так что по прошлым периодам Максимум должен возвращать одну и ту же ссылку.

может вернуть вам ссылки из разных строк выборки. Это ничего не портит? (11) sommid, да вероятность не исключаю. И какое есть решение? (12) идти последовательно: сначала определить максимум по одному полю, опять соединится - потом максимум по второму полю. так гарантируем получение данных по конкретной записи выборки (14) sommid, так в чем разница, если я сначала сгруппирую по 3 реквизитам и возьму максимум, а потом еще раз так сделаю только максимум уже будет на другом реквизите? (16) группируем последовательно по одному полю.
сначала по Сотруднику, потом соединяемся и получаем Пользователей именно этого отрудника => следующий максимум по пользователям будет выбираться уже из меньшего количества записей и это не равносильно если мы сразу сгруппируем по двум полям по максимуму На текущий момент сотрудником и пользователей создают руками. (20) sommid, вы пропустили втОбщая.Сотрудник КАК Сотрудник в первой части? Или откуда он потом появился во второй? (21) в первой убрал намеренно, во второй он должен взяться из общей таблицы

(22) sommid, короче соединить с исходной.

Так в чем еще раз будет разница на конкретном примере?

Контрагент События Сотрудник Ответственный
К1 2 Иванов (УИД 001..) Пользователь1 (УИД 002..)
К2 2 Петров (УИД 002..) Пользователь2 (УИД 001..)

если сразу выбрать максимум по обоим полям то получим запись "К1, 2, Петров, Пользователь1" - но это некорректно, т.к. такой записи у нас нет

Если идем пошагаво, то сначала находим максимум по Ответственный - это Пользователь1, делаем соединение с общей таблицей и получаем
К1 2 Иванов (УИД 001..) Пользователь1 (УИД 002..)
теперь по записям этой таблицы делаем максимум по Сотруднику (в данном случае запись одна, но в теории м.б. и несколько)
и получаем результат "К1, 2, Иванов , Пользователь1"

(24) sommid, т.е. УИД это например создали в базе Сотрудника1, Сотрудника2. Затем создали Пользователя2 и Пользователя1.

И вот в такой ситуации будет косяк в связке?

Об этом и писали в (7), а можно ли не по ссылке, а по строке взять максимум, так я бы оптимизировал бы запрос сразу?

(25) по последовательности создания не скажешь, что уид последнего созданного элемента больше предыдущего.. я думаю там рандом.
Максимум по строке не изменит сути проблемы, уид это ж тоже строка, ну будет вместо нее другая строка

К2 2 ИвановСтрокой ЮзерИвановСтрокой
К2 2 ПетровСтрокой ПетровСтрокой
ИвановСтрокой < ПетровСтрокой
ЮзерИвановСтрокой > ПетровСтрокой
И опять получим тоже самое при одновременном получении максимума: К2 2 ПетровСтрокой ЮзерИвановСтрокой - а такой записи нет

(26) sommid, пример плохой у вас.
УИД - это уникальный идентификатор и хоть он и похож на строку, но в базе это не тип строка! (27) а в таблице SQL? мы же работаем в запросе, а не с явным типом 1С (28) sommid, т.е. сортировка идет по УИДу ссылки в запросе? (29) я думаю, что сортировка идет по основному представлению, а сравнение по уиду.. но, конечно, хотелось бы подтвердить каким-нибудь источником. надо гуглить )
разные результаты в моей базе, значит и сортировка по УИД

(31) sommid, если упорядочивать по ссылка, то необходимо АВТОУПОРЯДОЧИВАНИЕ:
УПОРЯДОЧИТЬ ПО
Ссылка
АВТОУПОРЯДОЧИВАНИЕ

Тогда результат запросов одинаковый

Сортировать по Количеству УБЫВ и ВЫБРАТЬ ПЕРВЫЕ 1 не предлагали еще?) Ну тогда в итоговой таблице получить Максимум Количество для каждого Контрагента, а затем соединить внутренним соединением полученную таблицу максимумов с втПолная по условию втПолная.Количество = втПолнаяМаксимумы.Количество и втПолная.Контрагент = втПолнаяМаксимумы.Контрагент, а пользователя брать из втПолная(тогда не придется полагаться на Максимум(пользователь).
Написал бы код, да нет под рукой конфы с регистром РаботникиОрганизаций. (35) так это и так есть в изначальном запросе. проблема, когда для максимума конкретного контрагента есть несколько вариантов (см. коммент (3), (4)) - с ними автор и борется

Итоги можно опустить.

Стоит обратить внимание на втПолная . Заметил такую фичу. Был сотрудник на полную ставку и этот же сотрудник как внешний совместитель. В итоге простой группировки было мало. Сделал максимум т.к. в конечном запросе результат отличался на 8 строк.

Цель: найти первый / последний документ в периоде в запросе? (именно ссылку на документ, а не дату документа) Конструкции МИНИМУМ(БухИтоги.Регистратор) и МАКСИМУМ(БухИтоги.Регистратор) выдают некорректные значения. Похоже, что сравнивает по представлениям документа (т.е. влияет даже название документа), а не по дате. Конструкции МИНИМУМ(БухИтоги.Регистратор.Ссылка) и МАКСИМУМ(БухИтоги.Регистратор.Ссылка) также выдают неправильные данные Кто подскажет как найти ссылку на первый / последний документ в периоде в запросе? Вариант ВЫБРАТЬ ПЕРВЫЕ 1 БухИтоги.Регистратор ИЗ . не подходит по причине, что надо искать по нескольким контрагентам, т.е. конечный вариант хотелось бы видеть вроде: БухИтоги1.Субконто1 КАК Контрагент, БухИтоги1.Субконто2 КАК Договор, МИНИМУМ(БухИтоги2.Регистратор), МАКСИМУМ(БухИтоги2.Регистратор) Вариант с "ВЫБРАТЬ ПЕРВЫЕ 1" даже не представляю как написать.

Допустим, есть таблица "Табл": Регистратор, контрагент, сумма. Нужно получить последние документы по всем контрагентам: Выбрать Регистратор, Контрагент, Сумма Из Табл КАК Табл1 Внутреннее Соединение (

А сравнивает он их по ссылкам (32-символьный уникальный ключ)

+ Первый и последний будут выглядить так: Выбрать Регистратор, Контрагент, Сумма Из Табл КАК Табл1 Внутреннее Соединение ( Выбрать Регистратор, Контрагент, Сумма Из Табл КАК Табл1 Внутреннее Соединение (

Т.е. Вы хотите сказать что Табл2.Дата = Табл1.Регистратор.Дата будет сравнивать не до секунды, а точно - документ в документ?

Точно подмечено. Я запрос писал прямо здесь и в 4 утра уже засыпал..) Лучше конечно использовать Регистратор.МоментВремени, который уникален.

хотя нет. С моментом времени я ерунду сказал - его в конструкции МАКСИМУМ нельзя использовать. Можно отобрать по наибольшим и наименьшим датам и упорядочить по МоментВремени и после этого при обходе лишнее отфильтровать..

Можно так: ЗЫ: Постольку, для документов одинакового вида внутренний идентификатор выделяется в зависимости от времени ввода документа в пределах секунды, то МАКСИМУМ(Ссылка) вернет последний документ в секунде. ЗЫЗЫ: Проверил все работает, но за теорию (см. выше) не ручаюсь ;-)

А насчет внутреннего идентификатора можно сомневаться..

Вроде выстраиваются правильно, хотя на партнерском Нуралиев говорил что внутренний идентификатор может присваиваться как угодно.

По ссылке МАКСИМУМ и МИНИМУМ вообще в пределах базы НЕ работает - ЭТО ТОЧНО! Проверено. А вот в течение секунды. Гм. надо пробовать.

Т.е. я хотел сказать что МАКСИМУМ(Регистратор.Ссылка) в пределах базы сортируется неправильно. Может в течение секунды и сортирует правильно, но как проверить? МоментВремени - выдаёт точную позицию документа, но это есть виртуальное поле, и его нельзя использовать в МАКСИМУМ МИНИМУМ. Спасибо за . Но боюсь что это может не сработать. Я не уверен насчёт >>ЗЫ: Постольку, для документов одинакового вида внутренний идентификатор >>выделяется в зависимости от времени ввода документа в пределах секунды, то >>МАКСИМУМ(Ссылка) вернет последний документ в секунде. Где Вы это прочли?

Войдите как ученик, чтобы получить доступ к материалам школы

Язык запросов 1С 8.3 для начинающих программистов: группировка

Автор уроков и преподаватель школы: Владимир Милькин

Группировка в запросах

Давайте запросим из таблицы Справочник.Еда следующие реквизиты: Наименование, Цвет и Калорийность:

01

Теперь предположим, что нам необходимо вычислить суммарную калорийность продуктов для каждого цвета.

Алгоритм для жёлтого цвета будет такой:

  1. Находим все строчки у которых в поле Цвет стоит Жёлтый.
  2. Это будут строчки №1, 6, 8 и 9.
  3. Суммируем поле Калорийность для каждой из этих строк: 89 + 31 + 340 + 536
  4. Получаем, что для жёлтого цвета суммарная калорийность равна 996.

И так для каждого цвета.

Описанный выше процесс называется группировкой . Таким образом, группировка - это "схлопывание" (свёртка) строчек таблицы по определенному признаку.

При группировке все поля делятся на две группы:

  • Группировочные - это как раз те поля, по которым идёт свёртка. В нашем случае таким полем является Цвет.
  • Группируемые - это те поля, которые сворачиваются (схлопываются, объединяются). В нашем случае таким полем является Калорийность.

01

Группируемые поля не могут быть сами по себе. К ним обязательно применяется одна из агрегатных функций: СУММА, СРЕДНЕЕ, МИНИМУМ, МАКСИМУМ, КОЛИЧЕСТВО, КОЛИЧЕСТВО РАЗЛИЧНЫЕ:

02

Агрегатная функция СУММА

Это как раз случай, который мы разбирали. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Все строки группируются по группировочным полям (Цвет), а группируемые поля (Калорийность) суммируются:

сумма

Агрегатная функция СРЕДНЕЕ

В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится среднее значение:

среднее

Агрегатная функция МИНИМУМ

В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится минимальное значение:

минимум

Агрегатная функция МАКСИМУМ

В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится максимальное значение:

максимум

Агрегатная функция КОЛИЧЕСТВО

В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится их количество :

количество

Агрегатная функция КОЛИЧЕСТВО РАЗЛИЧНЫЕ

В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится количество элементов с различными значениями:

количество различные

Функция КОЛИЧЕСТВО РАЗЛИЧНЫЕ требует пояснения, потому что на выбранном примере её результат совпадает с функцией КОЛИЧЕСТВО. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Вот более показательный пример, который всё объясняет:

03

Группировка без группируемых полей и агрегатных функций

Использование агрегатных функций в запросе не требуется, если результатом запроса будут только группировочные поля:

06

К примеру, сделаем выборку всех вкусов, которые встречаются среди еды:

Как видите вкусы повторяются - давайте их сгруппируем:

Таким образом, мы сделали группировку только по группировочным полям (Вкус). Группируемые поля, а следовательно и агрегатные функции нам не понадобились.

Группировка без группировочных полей

Соответственно использование группировочных полей также не требуется, если результатом запроса будут только группируемые поля:

12

К примеру, получим результаты агрегатных функций применительно к полю Калорийность без группировочных полей (то есть по всей таблице):

13

Группировка по нескольким полям

Группировочных (как впрочем и группируемых) полей может быть сколь угодно много. В запросе они перечисляются через запятую.

Читайте также: