Ссылка максимум в 1с какая выберется
Войдите как ученик, чтобы получить доступ к материалам школы
Язык запросов 1С 8.3 для начинающих программистов: объединение
Автор уроков и преподаватель школы: Владимир Милькин
Объединение в запросах
В языке запросов имеется возможность объединять несколько запросов. При этом записи, полученные с помощью каждого из объединяемых запросов, будут собраны в один результат запроса.
Как всегда начнём с примера.
Пусть требуется написать запрос, который возвращает все названия цветов и вкусов в одной таблице.
Цвета мы умеем выбирать так:
А вот, чтобы объединить эти два результата в один как раз и потребуется операция объединения:
Обратите внимание на то, что операция объединения вовсе не гарантирует, что элементы будут идти в каком-то определённом порядке. В общем случае они могут следовать друг за другом как угодно, поэтому если важен порядок необходимо как и всегда указывать его явно (через секцию УПОРЯДОЧИТЬ).
Требования к запросам, участвующим в объединении
У объединяемых запросов должно быть одинаковое количество полей . Иначе мы получим такую ошибку:
В объединяемых запросах соответствующие друг другу (по порядку) поля должны иметь одинаковый тип . Но это требование, в отличие от предыдущего, не является обязательным. Если соответствующие друг другу поля имеют разный тип, то поле результата будет иметь СОСТАВНОЙ тип, который разбирался нами на одном из прошлых уроков:
Несмотря на то, что поле первого запроса имеет тип СТРОКА, а второго ЧИСЛО, нам удалось объединить их в одну таблицу. Но тип результатирующего поля стал составным и нам придётся учитывать это в дальнейшем. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Кстати, вы заметили, что поле итоговой таблицы (после объединения) называется Наименование, а не Калорийность? Эта такое правило : поля итоговой таблицы всегда имеют названия совпадающие с именами описанными в первом из объединяемых запросов.
Объединение более двух запросов
При объединении каждый запрос собирает данные независимо, а уже затем результаты объединяются в один. Количество объединяемых запросов не ограничено.
Напишем объединение трёх запросов:
Повторяющиеся строки
Давайте объединим один и тот же запрос сам с собой:
Обратите внимание на то, что мы объединили две одинаковые таблицы цветов, а в результате каждый цвет встречается ровно один раз.
Всё потому, что по умолчанию при объединении запросов полностью одинаковые строки в результате запроса, заменяются одной. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Если требуется, чтобы были оставлены в том числе одинаковые строки (дубли), необходимо указать ключевое слово ВСЕ:
Упорядочивание при объединении
Пытаться отдельно упорядочивать результаты запросов, участвующих в объединении не имеет смысла. Поэтому при попытке написать:
Упорядочивать можно только результат объединения :
Обратите внимание на то, что секция УПОРЯДОЧИТЬ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.
Подведение итогов при объединении
Пытаться отдельно подводить итоги по запросам, участвующим в объединении, также не имеет смысла. Поэтому при попытке написать:
Подводить итоги можно только по результату объединения :
Обратите внимание на то, что секция ИТОГИ ПО в данном случае относится не к последнему запросу, а уже к результату объединения запросов.
Рабочий пример
Давайте решим такую задачу. Требуется вывести для каждого элемента справочника Еда закупленное и проданное количество за весь период.
Поступление еды у нас в базе происходит документом ПоступлениеЕды. У документа есть табличная часть Еда, с реквизитами Номенклатура и Количество.
Сначала выберем все строки табличной части Еда из всех поступлений:
Теперь сгруппируем этот результат по еде с суммированием количества:
Аналогичным образом получим продажу еды из документов ПродажаЕды:
Осталось объединить эти два запроса:
Обратите внимание на то, как мы дополнили оба запроса ещё одним полем СУММА(0). Мы вынуждены были сделать это, так как оба запроса содержат по два поля, а объединение запросов должно содержать три поля. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Если бы мы не сделали этого, а написали просто:
Протестировал эту реализацию, в конечный запрос не то что 1 строка, а целых две.
т.е. они оба так и остались:
Контрагент1 Пользователь1 Сотрудник1 2
Контрагент1 Пользователь2 Сотрудник2 2
(7) максимум от ссылочного типа будет определятся по строке УИД этой ссылки,
для уже созданных справочников маловероятно, что будут менятся УИДы, так что по прошлым периодам Максимум должен возвращать одну и ту же ссылку.
сначала по Сотруднику, потом соединяемся и получаем Пользователей именно этого отрудника => следующий максимум по пользователям будет выбираться уже из меньшего количества записей и это не равносильно если мы сразу сгруппируем по двум полям по максимуму На текущий момент сотрудником и пользователей создают руками. (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 ПетровСтрокой ЮзерИвановСтрокой - а такой записи нет
УИД - это уникальный идентификатор и хоть он и похож на строку, но в базе это не тип строка! (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 для начинающих программистов: группировка
Автор уроков и преподаватель школы: Владимир Милькин
Группировка в запросах
Давайте запросим из таблицы Справочник.Еда следующие реквизиты: Наименование, Цвет и Калорийность:
Теперь предположим, что нам необходимо вычислить суммарную калорийность продуктов для каждого цвета.
Алгоритм для жёлтого цвета будет такой:
- Находим все строчки у которых в поле Цвет стоит Жёлтый.
- Это будут строчки №1, 6, 8 и 9.
- Суммируем поле Калорийность для каждой из этих строк: 89 + 31 + 340 + 536
- Получаем, что для жёлтого цвета суммарная калорийность равна 996.
И так для каждого цвета.
Описанный выше процесс называется группировкой . Таким образом, группировка - это "схлопывание" (свёртка) строчек таблицы по определенному признаку.
При группировке все поля делятся на две группы:
- Группировочные - это как раз те поля, по которым идёт свёртка. В нашем случае таким полем является Цвет.
- Группируемые - это те поля, которые сворачиваются (схлопываются, объединяются). В нашем случае таким полем является Калорийность.
Группируемые поля не могут быть сами по себе. К ним обязательно применяется одна из агрегатных функций: СУММА, СРЕДНЕЕ, МИНИМУМ, МАКСИМУМ, КОЛИЧЕСТВО, КОЛИЧЕСТВО РАЗЛИЧНЫЕ:
Агрегатная функция СУММА
Это как раз случай, который мы разбирали. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Все строки группируются по группировочным полям (Цвет), а группируемые поля (Калорийность) суммируются:
Агрегатная функция СРЕДНЕЕ
В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится среднее значение:
Агрегатная функция МИНИМУМ
В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится минимальное значение:
Агрегатная функция МАКСИМУМ
В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится максимальное значение:
Агрегатная функция КОЛИЧЕСТВО
В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится их количество :
Агрегатная функция КОЛИЧЕСТВО РАЗЛИЧНЫЕ
В этом случае все строки группируются по группировочным полям (Цвет), а среди группируемых полей (Калорийность) находится количество элементов с различными значениями:
Функция КОЛИЧЕСТВО РАЗЛИЧНЫЕ требует пояснения, потому что на выбранном примере её результат совпадает с функцией КОЛИЧЕСТВО. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Вот более показательный пример, который всё объясняет:
Группировка без группируемых полей и агрегатных функций
Использование агрегатных функций в запросе не требуется, если результатом запроса будут только группировочные поля:
К примеру, сделаем выборку всех вкусов, которые встречаются среди еды:
Как видите вкусы повторяются - давайте их сгруппируем:
Таким образом, мы сделали группировку только по группировочным полям (Вкус). Группируемые поля, а следовательно и агрегатные функции нам не понадобились.
Группировка без группировочных полей
Соответственно использование группировочных полей также не требуется, если результатом запроса будут только группируемые поля:
К примеру, получим результаты агрегатных функций применительно к полю Калорийность без группировочных полей (то есть по всей таблице):
Группировка по нескольким полям
Группировочных (как впрочем и группируемых) полей может быть сколь угодно много. В запросе они перечисляются через запятую.
Читайте также: