Малки трикове за големи заявки. Подреждане на резултатите от заявката Оператор в йерархията

23.06.2023

Заявкиса предназначени да извличат и обработват информация от базата данни, за да я предоставят на потребителя в необходимата форма. Обработката тук означава групиране на полета, сортиране на редове, изчисляване на общи суми и т.н. Не можете да променяте данни с помощта на заявки в 1C!

Заявката се изпълнява съгласно дадените инструкции − текст на заявката. Текстът на заявката се компилира в съответствие със синтаксиса и правилата език за заявки. Езикът за заявки 1C:Enterprise 8 се основава на стандарта SQL, но има някои разлики и разширения.

Схема за работа със заявка

Общата схема на работа със заявка се състои от няколко последователни етапа:

  1. Създаване на обект Request и задаване на текста на заявката;
  2. Задаване на параметри на заявката;
  3. Изпълнение на заявка и получаване на резултата;
  4. Заобикаляне на резултата от заявката и обработка на получените данни.

1. Обект Заявкапритежава имота Текст, на който трябва да присвоите текста на заявката.

// Вариант 1
Заявка = Нова заявка;
Заявка . Текст =
„ИЗБЕРЕТЕ
| Валутни курсове. Период,
| Валутни курсове. Валута,
| Валутни курсове
| ОТ

|КЪДЕ
;

// Вариант 2
Заявка = Нова заявка(„ИЗБЕРЕТЕ
| Валутни курсове. Период,
| Валутни курсове. Валута,
| Валутни курсове
| ОТ
| Регистър на информацията. Валутни курсове КАТО валутни курсове
|КЪДЕ
| Валутни курсове. Валута = &Валута");

2. Задаването на стойностите на параметрите се извършва по метода SetParameter(< Имя>, < Значение>) . Параметрите в текста на заявката са обозначени със символа „ & " и обикновено се използват в условия за избор (секция WHERE) и в параметри на виртуална таблица.

Заявка);

3. След задаване на текста и настройка на параметрите заявката трябва да се изпълни и да се получи резултатът от изпълнението. Изпълнението се извършва от метода Execute(), който връща обект Резултат от заявката. От резултата от заявката можете:

  • вземете селекция с помощта на метода Select (< ТипОбхода>, < Группировки>, < ГруппировкиДляЗначенийГруппировок>) ;
  • качвайте стойности в таблица със стойности или дърво със стойности, като използвате метода за качване (< ТипОбхода>) .

// Получаване на проба

проба = Резултат от заявката. Изберете();

// Вземете таблица със стойности
RequestResult = Заявка. Изпълнение();
Таблица = Резултат от заявката. Разтоварвам();

4. Можете да заобиколите избора на резултат от заявката с помощта на цикъл:

чао Sample.Next() цикъл
Доклад(Избор.Курс);
EndCycle;

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

// Етап 1. Създаване на заявка и задаване на текста на заявката
Заявка = Нова заявка;
Заявка . Текст =
„ИЗБЕРЕТЕ
| Валутни курсове. Период,
| Валутни курсове. Валута,
| Валутни курсове
| ОТ
| Регистър на информацията. Валутни курсове КАТО валутни курсове
|КЪДЕ
| Валутни курсове. Валута = &Валута";

// Етап 2. Задаване на параметри
Заявка . SetParameter("Валута" , SelectedCurrency);

// Етап 3. Изпълнение на заявката и получаване на извадката
RequestResult = Заявка. Изпълнение();
проба = Резултат от заявката. Изберете();

// Обхождане на селекцията
чао Sample.Next() цикъл
Доклад(Избор.Курс);
EndCycle;

Състав на текста на заявката

Текстът на искането се състои от няколко раздела:

  1. Описание на заявката— списък с избираеми полета и източници на данни;
  2. Обединяване на заявки— изрази „ОБЕДИНЯВАНЕ“ и „ОБЕДИНЯВАНЕ НА ВСИЧКИ“;
  3. Организиране на резултатите— изразът „ПОРЪЧАЙ ОТ...“;
  4. Автоматична поръчка— израз „АВТОМАТИЧНА ПОРЪЧКА“;
  5. Описание на резултатите- изразът „РЕЗУЛТАТИ ... ОТ ...“.

Само първият раздел е задължителен.

Временни таблици и пакетни заявки

1C езикът за заявки поддържа използването временни маси— таблици, получени в резултат на заявка и съхранявани временно.

Често можете да срещнете ситуация, в която трябва да използвате не таблици от база данни като източник на заявка, а резултат от изпълнение на друга заявка. Този проблем може да бъде разрешен с помощта на вложени заявки или временни маси. Използването на временни таблици ви позволява да опростите текста на сложна заявка, като я разделите на съставни части, а също така в някои случаи ускорявате изпълнението на заявката и намалявате броя на заключванията. За да работите с временни таблици, използвайте обекта Мениджър на разписание. Създава се временна таблица с помощта на ключова дума PLACE, последвано от името на временната таблица.

ManagerVT = Нов TemporaryTablesManager;
Заявка = Нова заявка;
Заявка . TemporaryTablesManager = VTManager;

Заявка . Текст =
„ИЗБЕРЕТЕ
| Валути.Код,
| Валути. Име
|Място във валути
| ОТ
| Директория. Валути КАТО Валути";

RequestResult = Заявка. Изпълнение();

За да използвате временната таблица VTVcurrency в други заявки, трябва да присвоите общ мениджър на временни таблици към тези заявки — VT Manager.

Пакетна заявкае заявка, която съдържа няколко заявки, разделени със знака „;“. При изпълнение на пакетна заявка, всички заявки, включени в нея, се изпълняват последователно и резултатите от всички временни таблици са достъпни за всички следващи заявки. Не е необходимо изрично присвояване на временен мениджър на таблици на пакетни заявки. Ако не е зададен временен мениджър на таблици, тогава всички временни таблици ще бъдат изтрити веднага след изпълнение на заявката.

За пакетни заявки е наличен методът ExecuteBatch(), който изпълнява всички заявки и връща масив от резултати. Временните таблици в пакетна заявка ще бъдат представени от таблица с един ред и една колона „Брой“, която съхранява броя на записите. За отстраняване на грешки в пакетни заявки можете да използвате метода Изпълнение на партида С МЕЖДИННИ ДАННИ() : Връща действителното съдържание на временните таблици, а не броя на записите.

// Пример за работа с групова заявка
Заявка = Нова заявка;
Заявка . Текст =
„ИЗБЕРЕТЕ
| Валути. Име
| ОТ
| Справочник. Валути AS Валути
|;
|ИЗБЕРЕТЕ
| Номенклатура. Наименование
| ОТ
| Справочник Номенклатура АС Номенклатура";

BatchResult = Заявка. ExecuteBatch();

TZ Валути =PacketResult[ 0 ]. Разтоварване();
TZNomenclature = Резултат от пакета[ 1 ]. Разтоварване();

// Пример за използване на временни таблици в групова заявка
Заявка = Нова заявка;
Заявка . Текст =
„ИЗБЕРЕТЕ
| Продукти Връзка КАК ДА Продукт
|PLACE WTT Продукти
| ОТ
| Справочник.Номенклатура КАК Продукти
|КЪДЕ
| Продукти.Производител = &Производител
|;
|ИЗБЕРЕТЕ
| VTTProducts.Продукт,
| Професионално училище Количество,.
| Професионална гимназия. Цена,
| Професионална гимназия. Връзка AS DocumentReceipts
| ОТ
| VT продукти AS VT продукти
| ЛЯВА ВРЪЗКА Документ за получаване на стоки и услуги AS PTU
| Софтуер VTProducts.Product = PTU.Номенклатура"
;

Заявка . SetParameter( "Производител", производител);

RequestResult = Заявка. Изпълнение();
проба = Резултат от заявката. Изберете();

чао Sample.Next() цикъл

EndCycle;

Виртуални маси

Виртуални маси- това са таблици, които не се съхраняват в базата данни, а се генерират от платформата. В основата си това са вложени заявки към една или повече физически таблици, изпълнявани от платформата. Виртуалните таблици получават информация само от регистри и са предназначени основно за решаване на тясно специализирани проблеми.

Съществуват следните виртуални таблици (възможните параметри са посочени в скоби):

  • За информационни регистри:
    • SliceFirst(<Период>, <Условие>) — най-ранните записи за посочената дата;
    • SliceLast(<Период>, <Условие>) — последните записи за посочената дата;
  • За регистри за натрупване:
    • остатъци (<Период>, <Условие>) — салда към посочената дата;
    • Революции (<НачалоПериода>, <КонецПериода>, <Периодичность>, <Условие>) — оборот за периода;
    • RemainsAndTurnover(<НачалоПериода>, <КонецПериода>, <Периодичность>, <МетодДополненияПериодов>, <Условие>) — салда и обороти за периода;
  • За счетоводни регистри:
    • остатъци (<Период>, <УсловиеСчета>, <Субконто>, <Условие>) — салда към посочената дата в контекста на сметка, измерения и подсметки;
    • Революции (<НачалоПериода>, <КонецПериода>, <Периодичность>, <УсловиеСчета>, <Субконто>, <Условие>, <УсловиеКорСчета>, <КорСубконто>) — оборот за периода в контекста на сметки, измервания, кор. сметки, подконт., кор. подконто;
    • RemainsAndTurnover(<НачалоПериода>, <КонецПериода>, <Периодичность>, <МетодДополненияПериодов>, <УсловиеСчета>, <Субконто>, <Условие>) — салда и обороти по сметки, измервания и подсметки;
    • ОборотDtKt(<НачалоПериода>, <КонецПериода>, <Периодичность>, <УсловиеСчетаДт>, <СубконтоДт>, <УсловиеСчетаКт>, <СубконтоКт>, <Условие>) — оборот за периода по сметка Дт, сметка Кт, Подконто Дт, Подконто Кт;
    • MovementsSubconto(<НачалоПериода>, <КонецПериода>, <Условие>, <Порядок>, <Первые>) — движения заедно с подконто стойности;
  • За изчислителни регистри:
    • Основа (<ИзмеренияОсновногоРегистра>, <ИзмеренияБазовогоРегистра>, <Разрезы>, <Условие>) — основни данни на калкулационния регистър;
    • DataGraphics(<Условие>)—графични данни;
    • ActualActionPeriod(<Условие>) е действителният период на валидност.

Когато работите с виртуални таблици, трябва да прилагате селекции в параметрите на виртуалните таблици, а не в условието WHERE. Времето за изпълнение на заявката зависи до голяма степен от това.

Конструктор на заявки

За да се ускори въвеждането на текстове на заявки, платформата разполага със специални инструменти: Конструктор на заявкиИ Конструктор на заявки с обработка на резултата. За да извикате конструктори, трябва да щракнете с десния бутон и да изберете необходимия елемент:

Конструкторите могат да бъдат извикани и от главното меню Текст.

Използвайки конструктора на заявки, програмистът може интерактивно да конструира текста на заявката. За да направите това, изберете необходимите таблици и полета с мишката, установете връзки, групи, суми и т.н. Този подходви позволява да спестите време и да се отървете от възможни грешки. В резултат на своята работа конструкторът на заявката генерира текста на заявката.

Конструкторът на заявка с обработка на резултата, в допълнение към генерирането на текста на заявката, създава готов кодов фрагмент за получаване и обработка на данни.

Обект RequestSchema

Платформата ви позволява програмно да създавате и редактирате текста на заявката, като използвате обекта Схема на заявка. Един обект има едно свойство Партида от заявки, в който обектът съхранява свойствата на всички редактирани заявки в момента. Обектът RequestSchema поддържа следните методи:

  • SetQueryText(< Текст>) — попълва свойството Query Packet въз основа на изпратения текст на заявката;
  • GetQueryText() - връща текста на заявката, генериран въз основа на свойството Request Package;
  • FindParameters() - връща параметрите на заявката.

Нека да разгледаме пример за работа с обекта RequestSchema. Програмно генериране на текста на заявката

ПОРЪЧАЙТЕ ПО
Валути.Код

Кодът на вградения език може да изглежда така:

RequestScheme = Нова схема на заявка;
Пакет 1 = Схема на искане. RequestBatch[ 0 ];
Оператор1 = Пакет1. Оператори[ 0 ];
// добавяне на източник
RegisterTable = Оператор1. Източници. Добавяне ( "Директория. Валути", „Валути“ );
// добавяне на полета
FieldLink = Оператор1. Избираеми полета. Add("Валути.Връзка" , 0);
FieldCode = Оператор1. Избираеми полета. Add("Валути.Код", 1);
// указване на псевдоними на полета
Пакет 1 . Колони[ 0 ]. Псевдоним = "Валута";
Пакет 1 . Колони[ 1 ]. Псевдоним = "Код";
// добавяне на условие
Оператор1 . Избор. Добавяне ( „НЕ FlagDeletion“);
// добавяне на ред
Пакет 1 . ред. Добавяне (код на поле);
RequestText = RequestScheme. GetQueryText();

За генериране и изпълнение на заявки към таблици на база данни в платформата 1C се използва специален обект на език за програмиране Заявка. Този обект се създава чрез извикване на конструкцията Нова заявка. Заявката е удобна за използване, когато трябва да получите сложна извадка от данни, групирана и сортирана според нуждите. Класически пример за използване на заявка е получаването на обобщена информация за състоянието на регистъра за натрупване в определен момент от време. Освен това механизмът за заявки улеснява получаването на информация в различни периоди от време.

Тялото на заявката е инструкцията, според която заявката трябва да бъде изпълнена. Основният текст на заявката описва:

  • маси информационна база, използвани като източници на данни за заявки;
  • полета на таблица, които трябва да бъдат обработени в заявката;
  • правила за групиране;
  • сортиране на резултатите;
  • и т.н.
Инструкцията е съставена на специален език - езикът на заявките и се състои от отделни части - секции, изречения, ключови думи, функции, аритметични и логически оператори, коментари, константи и параметри.

Езикът на заявките на платформата 1C е много подобен на синтаксиса на други SQL езици, но има разлики. Основните предимства на вградения език за заявки са: дерефериране на полета, наличие на виртуални таблици, удобна работа с резултати, нетипизирани полета в заявки.

  • enum стойности;
  • предварително дефинирани данни:
  • справочници;
  • планове за типове характеристики;
  • сметкопланове;
  • планове за видове изчисления;
  • празни връзки;
  • стойности на точка на маршрут на бизнес процес.
Освен това текстът на заявката може да съдържа стойностите на системните изброявания, които могат да бъдат присвоени на полета в таблиците на базата данни: Тип движение на натрупване, Тип акаунт и Тип движение на счетоводство. Заявки за достъп до предварително дефинирани конфигурационни данни и системни изброени стойности с помощта на литерал от тип функция ЗНАЧЕНИЕ. Този литерал ви позволява да подобрите четливостта на заявката и да намалите броя на параметрите на заявката.

Пример за използване на литерал ЗНАЧЕНИЕ:
WHERE Град = СТОЙНОСТ(Директория.Градове.Москва)
WHERE City = VALUE(Directory.Cities.EmptyLink)
WHEREProductType = VALUE(Enumeration.ProductTypes.Service)
WHEREMovementType = VALUE(MovementTypeAccumulation.Incoming)
WHERE RoutePoint = VALUE(BusinessProcess.BusinessProcess1.RoutePoint.Action1

2) Използване на инструкциите АВТОМАТИЧНА ПОРЪЧКАИзпълнението на заявката може да отнеме много време, така че ако сортирането не е необходимо, тогава е по-добре да не го използвате изобщо. В повечето случаи е най-добре да използвате сортиране на инструкции ПОРЪЧАЙТЕ ПО.

Автоматичното подреждане работи съгласно следните принципи:

  • Ако клаузата ORDER BY е посочена в заявката, тогава всяка връзка към таблицата, открита в тази клауза, ще бъде заменена от полетата, по които таблицата е сортирана по подразбиране (за справочници това е кодът или името, за документи - дата на документа). Ако полето за сортиране се отнася за йерархична директория, тогава ще се приложи йерархично сортиране по тази директория.
  • Ако заявката не съдържа клаузата ORDER BY, но има клауза TOTAL, тогава резултатът от заявката ще бъде подреден по полетата, налични в клаузата TOTAL след ключовата дума BY, в същата последователност и, ако сумите са изчислени от референтни полета, след това от полетата за сортиране по подразбиране на таблиците, които са били реферирани.
  • Ако заявката не съдържа клаузите ORDER BY и TOTAL, но има клауза GROUP BY, тогава резултатът от заявката ще бъде подреден по присъстващите в клаузата полета в същата последователност и, ако групирането е извършено по референтни полета , след което по подразбиране полета за сортиране на таблици, които са били посочени.
  • Ако заявката не съдържа клаузи ORDER BY, TOTAL или GROUP BY, резултатът ще бъде подреден по полетата за сортиране по подразбиране за таблиците, от които са избрани данните, в реда, в който се показват в заявката.

Ако заявката съдържа клауза TOTAL, всяко общо ниво се подрежда отделно.

3) За да избегнете повторение на заявка към базата данни при показване на резултата от заявката на потребителя (например създаване на заявка или показване на резултата от заявката с помощта на документ с електронна таблица) е полезно да използвате инструкциите ВЪВЕДЕНИЕ ВРЪЗКИ, което ви позволява да получите представяне на референтна стойност.

Също така е възможно да се използват инструкции ИЗПЪЛНЕНИЕ- предназначени за получаване на низово представяне на стойност от произволен тип. Разликата между тези инструкции е, че в първия случай, ако инструкцията предаде връзка, резултатът ще бъде низ, в други случаи резултатът ще бъде стойността на предадения параметър. Във втория случай резултатът от инструкцията винаги ще бъде низ!

4) Ако заявката има поле със съставен тип, тогава за такива полета става необходимо да се преобразуват стойностите на полето в някои определен типизползвайки инструкции ЕКСПРЕСНО, което ще ви позволи да премахнете ненужните таблици от лявото съединение с поле от сложен тип данни и да ускорите изпълнението на заявката.

Пример:
Има регистър за натрупване на Остатъчни стоки, в който полето Регистратор е от съставен тип. В заявката се избират датата и номерът на документа за получаване на стоки, докато при достъп до данните за документа през полето Регистратор не се появяват много леви връзки на таблицата на регистъра за натрупване с таблиците на документите на регистратора.

ИЗБЕРЕТЕ
EXPRESS(Останалите стоки.Регистратор AS Документ.Получаване на стоки).Номер КАТО Номер на разписка,
EXPRESS(Останалите стоки.Регистратор AS Документ.Получаване на стоки).Дата КАТО Дата на получаване
ОТ
Регистър на натрупванията, оставащи стоки КАТО оставащи стоки

Ако преобразуването на типа не се счита за възможно, тогава резултатът от преобразуването на типа ще бъде NULL.

5) Не забравяйте за инструкциите РАЗРЕШЕНО, което означава, че заявката ще избере само записи, за които текущият потребител има права. Ако тази дума не е посочена, тогава ако заявката избере записи, за които потребителят няма права, заявката ще бъде неуспешна.

6) Ако заявката използва съединение и някои части от съединението съдържат вложени таблици (документ с таблична част), а в някои не, има нужда от допълване на списъка за избор с полета - празни вложени таблици. Това става с помощта на ключова дума EMPTYTABLE, след което в скоби са посочени псевдонимите на полетата, които ще съставят вложената таблица.

Пример:
// Изберете полета Число и Състав
// от виртуалната таблица Document.Expenditure
ИЗБЕРЕТЕ Връзка.Номер, ПРАЗНА ТАБЛИЦА.(№, артикул, количество) КАТО състав
ОТ Документ. Разходна фактура
КОМБИНИРАЙТЕ ВСИЧКО
ИЗБЕРЕТЕ Link.Number, Contents.(LineNumber, Product, Quantity)
ОТ Документ.Фактура Документ.Фактура.Състав.*
7) За да предотвратите появата на дублирани редове в резултата от заявката, трябва да използвате инструкцията РАЗЛИЧНИ, защото е по-нагледен и разбираем, както и инструкциите ГРУПИРАНЕ ПОизползвани за използване на групиране агрегатни функции. Ksati, когато използваш агрегатни функции, едно предложение ГРУПИРАНЕ ПОможе изобщо да не е посочено, но всички резултати от заявката ще бъдат групирани в един ред.

Пример:
// Необходимо е да разберете кои контрагенти като цяло
// стоките са изпратени за периода.
Изберете Различни
Документ.Фактура.Контрагент

8) Инструкции ГРУПИРАНЕ ПОви позволява да осъществявате достъп до полета от най-високо ниво, без да групирате резултатите по тези полета, ако към полетата на вложена таблица се прилагат агрегатни функции. Въпреки че в помощта на 1C се казва, че при групиране на резултатите от заявката, агрегатните функции трябва да бъдат посочени в списъка с полета за избор и в допълнение към агрегатните функции в списъка с полета за избор е разрешено да се посочат само полетата, чрез които се извършва групирането .

Пример:
ИЗБЕРЕТЕ
Получаване на стоки и услуги (СУМ (количество), номенклатура).
Връзка за получаване на стоки и услуги,
Получаване на стоки и услуги
ОТ
Документ. Получаване на стоки и услуги КАК Получаване на стоки и услуги
ГРУПИРАНЕ ПО
Получаване на стоки и услуги (Номенклатура).

9) Инструкции ISNULLима за цел да замени стойността NULL с друга стойност, но не забравяйте, че вторият параметър ще бъде преобразуван в типа на първия, ако типът на първия параметър е низ или число.

10) При достъп до главната таблица можете условно да получите достъп до данните в подчинената таблица. Тази функция се нарича дерефериране на полета на подчинена таблица.

Пример (търсене на документи, съдържащи конкретен продукт в табличния раздел):
ИЗБЕРЕТЕ
Вход.Връзка
ОТ
Document.Admission Където Entrance.Products.Nomenclature = &Номенклатура.

Предимството на тази заявка пред заявка в подчинената таблица Receipt.Goods е, че ако има дубликати в документи, резултатът от заявката ще върне само уникални документи, без да използва ключовата дума РАЗЛИЧНИ.

11) Интересна опция за оператор IN- това е проверка за включването на подреден набор в набор от такива набори (Поле1, Поле2, ..., ПолеN) IN (Поле1, Поле2, ..., ПолеN).

Пример:
ИЗБЕРЕТЕ
Контрагенти.Връзка
КЪДЕ
(Връзка към контрагенти, връзка към продукти) B
(ИЗБЕРЕТЕ Sales.Customer, Sales.Product
ОТ RegisterAccumulation.Sales AS Sales)
ОТ
Справочник на контрагентите,
Справочник.Продукти

12) Когато е възможно, използвайте виртуални масизаявки. При създаване на заявка системата предоставя множество виртуални таблици като източници на данни – това са таблици, които също са резултат от заявка, която системата генерира по време на изпълнение на съответния раздел от кода.

Разработчикът може самостоятелно да получи същите данни, които системата му предоставя като виртуални таблици, но алгоритъмът за получаване на тези данни няма да бъде оптимизиран, защото:

  • Всички виртуални таблици са параметризирани, т.е. на разработчика се дава възможност да зададе някои параметри, които системата да използва при генериране на заявка за създаване на виртуална таблица. В зависимост от това какви параметри на виртуалната таблица са посочени от разработчика, системата може да генерира РАЗЛИЧНИ заявки за получаване на същата виртуална таблица и те ще бъдат оптимизирани по отношение на предадените параметри.
  • Не винаги е възможно разработчикът да получи достъп до данните, до които системата има достъп.
13) В режим на работа клиент-сървър функцията ПОДНИЗ()реализиран с помощта на функцията SUBSTRING() на съответния SQL изразпредадени на сървъра на базата данни SQL данниСървър, който изчислява типа на резултата от функцията SUBSTRING(), използвайки сложни правила в зависимост от типа и стойностите на нейните параметри, както и в зависимост от контекста, в който се използва. В повечето случаи тези правила нямат ефект върху изпълнението на заявката, но има случаи, при които максималната дължина на низа на резултата, изчислена от SQL сървър. Важно е да имате предвид, че в някои контексти, когато използвате функцията SUBSTRING(), максималната дължина на нейния резултат може да бъде равна на максималната дължина на низ с ограничена дължина, която в SQL Server е 4000 знака. Това може да доведе до неочакван срив на заявката:
Доставчик на Microsoft OLE DB за SQL Server: Предупреждение: Процесорът на заявка не можа да създаде план за заявка от оптимизатора, тъй като общата дължина на всички колони в клаузата GROUP BY или ORDER BY надвишава 8000 байта.
HRESULT=80040E14, SQLSTATE=42000, собствен =8618
За да избегнете тази грешка, не се препоръчва да използвате функцията SUBSTRING() за преобразуване на низове с неограничена дължина в низове с ограничена дължина. Вместо това е по-добре да използвате cast оператора EXPRESS().

14) Използвайте с повишено внимание ИЛИв конструкцията WHERE, тъй като използването на условие OR може значително да „натежи“ заявката. Проблемът може да бъде решен с помощта на дизайна UNITE EVERYTHING.

Пример:
ИЗБЕРЕТЕ

ОТ

КЪДЕ
_Demo Contractors.Link = &Link1

КОМБИНИРАЙТЕ ВСИЧКО

ИЗБЕРЕТЕ
_Демо изпълнители.ИмеПълно
ОТ
Директория._Демо контрагенти КАК _Демо контрагенти
КЪДЕ
_Demo Contractors.Link = &Link2

15) Състояние НЕ ВЪВв конструкцията WHERE увеличава времето за изпълнение на заявката, тъй като е вид NOT (OR1 OR2 ... ORn), така че за големи таблици опитайте да използвате LEFT JOIN с условието IS NULL.

Пример:
ИЗБЕРЕТЕ
_Демо изпълнители.Връзка
ОТ
Директория._Демо контрагенти КАК _Демо контрагенти
ЛЯВА ВРЪЗКА Документ._Демо Поръчка на Купувач КАК ДА _Демо Поръчка на Купувач
Софтуер _Демо контрагенти = _Демо Поръчка на контрагента
КЪДЕ
_Демо Поръчка на Контрагента Е НУЛЕВ

15) При използване Временни масиТрябва да индексирате условието и обединените полета в тези таблици, НО когато използвате индекси, заявката може да бъде още по-бавна. Следователно е необходимо да се анализира всяка заявка с и без използване на индекс, да се измери скоростта на изпълнение на заявката и да се вземе окончателно решение.
Ако поставите данни във временна таблица, която първоначално е индексирана от някои полета, тогава временната таблица вече няма да има индекс на тези полета.

16) Ако не използвате Мениджър на временни таблици, тогава няма нужда изрично да изтривате временната таблица, тя ще бъде изтрита след завършване на груповата заявка, в противен случай трябва да изтриете временната таблица по един от следните начини: като използвате командата DESTROY в заявката, извиквайки TemporaryTableManager. Close() метод.

Има много текст в сравнение с предишната публикация, но не е по-различно.

1. Пълна форма на използване на оператор B.

В допълнение към формуляра, посочен в предишната публикация:

Поле В(&списък със стойности),

Също така в езиковите заявки на 1C са разрешени следните форми на използване на този оператор:

1.Поле B(&масив)

2.Поле В (&Стойност1,....&СтойностN),

3.Поле B (Изберете…..)или за множество полета:

(Поле1, Поле2) B (Изберете T.Field5, T.Field6 от таблица T), където T е таблица (физическа, виртуална или временна)

4.Поле V (&Таблица със стойности)или за множество полета:

(Поле1, Поле2) В (&таблица със стойности)

Опция за запис № 3 се нарича подзаявка.

Вариант № 4 има особеност: броят на полетата в таблицата със стойности трябва точно да съвпада с броя на полетата, спрямо които се извършва проверката. Освен това трябва да се има предвид, че при сравняване в няколко полета условието ще приеме стойност True само ако има съвпадение във всички полета едновременно.

2. Оператор в йерархията.

Този оператор може да се използва само за йерархични директории(и други йерархични обекти, например сметкоплан, план на видовете характеристики). По същество този оператор е много подобен на оператор B, но има напълно различно значение: операторът проверява дали елементът на директорията принадлежи към посочената група (или групи, вложени в посочената група).

Пример за използване: в заявка избираме всички елементи от директорията на номенклатурата, които са в продуктовата група „Мебели“ (за простота елементът на директория „Номенклатура“ Мебели е предварително дефиниран).

Request.Text = "SELECT Nomenclature.Link FROM Directory.Nomenclature AS Nomenclature

Заявка . SetParameter(" Група1", Директории. Номенклатура. Мебели);

Забележка 1: ако зададете празен елемент като аргумент на оператора В йерархията, всички елементи от директорията ще бъдат избрани (т.е. операторът в йерархията ще върне стойността True за всеки елемент от директорията, тъй като елементите и групите от най-високо ниво имат празна стойност на атрибута Parent), например: Заявка . SetParameter(" Group1", Директории. Номенклатура. EmptyLink());

Забележка 2: Операторът In Hierarchy е много мощен и ви позволява да проверявате членството в група за елементи на директория с неограничено ниво на влагане в рамките на една заявка (което не може да се направи по други начини), но скоростта на този оператор не е много висока, което е особено забележимо в големи директории.

3. Използване на конструктора на заявки.

Сред програмистите на 1C често възникват спорове относно използването на конструктор на заявка или отказ от използване на конструктор и писане на заявка ръчно. Въпреки това, според повечето програмисти, е необходимо да се използва конструктор, но понякога след това получената заявка се „завършва на ръка“. За да извикате дизайнера на заявки в който и да е модул, трябва да щракнете с десния бутон на мишката и да изберете „Конструктор на заявки“ или „Конструктор на заявки с обработка на резултата“ от падащото меню.

Основни предимства от използването на конструктора на заявки:

1. Видимост на всички налични конфигурационни обекти за изграждане на заявка (както и всички временни таблици на заявки и др.).

2. Точно посочване на имената и детайлите на полетата (тъй като те не се въвеждат ръчно, а се избират от списък).

3. Опростено показване на връзките между заявка и обекти на условие.

4. Относително изолирана работа по всяка част от заявката (всяка заявка в пакетна заявка или отделна заявка при комбиниране на заявки).

5. Абсолютно надеждни данни за „съществуващите“ виртуални таблици в тази конфигурация.

4. Работа с дати в заявки (дата, момент във времето, граница)

В инструментите за разработка на 1C, започвайки от версия 8.0, типът данни Date се превърна в комбинация от дата и час. И всичко би било наред, но и тук има някои особености.

1 Проблем.Времето за създаване на документи може да се определи само с точност до секунда, тоест ако изпълним следния код два пъти с кратка пауза:

Док

Док

Док = Документи. идвам Създаване на документ(); Док. Дата = CurrentDate();

Док Doc.Write();

= Документи. Консумация. Създаване на документ(); Док. Дата = CurrentDate();

Doc.Write();

И след това изпълнете следната заявка:

КОМБИНИРАЙТЕ ВСИЧКО

ПОРЪЧАЙ ПО Дата

В рамките на 1 секунда първо идват „Входящите“ документи от тази секунда, а след това „Изходните“ документи от тази секунда, като номерата на документите са строго във възходящ ред (в нашия случай, поради автоматичното номериране на документите, това означава в реда на създаване). Остава да се реши един малък проблем - да се организират документите в рамките на секунда в реалния ред на тяхното създаване, а не само за всеки тип документ - ако не е имало задача да се реши този проблем предварително - той не е разрешим по принцип.

Забележка: TimePoint съдържа дата, час и препратка към обект на база данни. И защото връзката съдържа кода на типа обект и уникален номеробект - тогава сортирането в рамките на една секунда по Instant of Time ще даде като резултат групи от различни типове обекти в рамките на групи, които са подредени, но не са „смесени“ един с друг.

Как да разрешите този проблем:

Вариант 1: ако самите номера на документите не са важни, можете да създадете номератор на документа и тогава номерът на документа ще съответства на неговия сериен номер, когато е създаден. Това решение е много лошо с оглед на отказа от непрекъсната номерация на документите.

Опция 2: въведете допълнително идентификационно поле и преди да запишете документ с празна стойност за това поле, получете стойността на това поле за този документ от всеки независим от сесията източник, който може да бъде специален запис непериодичен регистърИнформация и стойност, записани във външен текстов или друг файл или Com-услуга, специално написана за тази цел и др. и запишете получената стойност в това поле и увеличете записаната стойност с единица.

2 Проблем. Избор на време за изпълнение на заявка за получаване на салда. Когато се изпълняват много заявки, е необходимо да се посочи краят на периода на вземане на проби (т.е. моментът, в който са получени балансите). Изглежда съвсем правилно да се каже следното:

Заявка . SetParameter( " Край на периода " , Краен месец(текуща дата())));

Но всъщност заявката за получаване на салда ще бъде изпълнена от началото на посочената дата (която е дата + час). Като се има предвид, че края на месеца (Дата (2012, 10, 29)) = 31.10.12 23:59:59

Оказва се, че сме загубили обороти, генерирани от движения (документи) за последната секунда на периода и ще получим салда секунда преди края на месеца, а не към края на месеца! Тази функция особено често води до грешка при получаване на баланси при импортиране на първоначални баланси (когато огромен брой документи могат да се поберат в последната секунда) и в организации, работещи в режим 7*24.

Как да разрешите този проблем:

Вариант 1: добавете 1 секунда към края на периода:

Заявка . SetParameter( " Край на периода " , EndMonth(CurrentDate())+1);

Вариант 2: използвайте Border обект, специално създаден за тази цел:

PeriodBorder = Нова граница(EndMonth(CurrentDate())+ 1, BorderType. Изключени);

Заявка . SetParameter("Край на периода" , граница на периода);

Забележка : ако в заявка е необходимо да се избере според позицията на документ върху времевата ос, тогава втората опция е по-ясна, например:

PeriodBoundary = Нова граница(Document.TimePoint,BoundaryView.Excluding);

или ако движенията и този документ паднат:

PeriodBoundary = Нова граница(Document.TimePoint,BorderView.Include);

Бележка 2: Както правилно е отбелязано в коментарите, има още един плюс от работата с типа данни Border - не е нужно да мислите какво избирате баланси или обороти и няма нужда да преминавате към сложна заявка, в която баланси и обороти се избират 2 параметъра, описващи момента, в който се прави избора (един за обороти, втори за остатъци).

5. Извадка по групи, резултати.

В допълнение към обичайния избор на резултати от заявки за йерархични директории, има възможност за йерархичен избор на резултати, което означава: нека нашата номенклатурна директория има следното съдържание на данни:

Инструменти

Файл

Тогава обичайната примерна заявка изглежда така:

проба = Искане. Изпълни(). Изберете();

Той ще създаде списък с елементи и групи, най-общо казано, в произволен ред (ако подреждането не е направено в заявката), но често трябва да изберете резултата, като вземете предвид йерархичното подчинение, тогава тази задача се изпълнява чрез лека модификация на заявката и малко по-сложен код за избор:

Заявка = Нова заявка;

Заявка . Текст = "ИЗБЕРЕТЕ номенклатура. Връзка КАТО номенклатура ОТ директория. Номенклатура КАТО номенклатура

РЕЗУЛТАТИ ПО НОМЕНКЛАТУРНАТА ЙЕРАРХИЯ“;

проба = Request.Run(). Select(BypassQueryResult.ByGroupingSIhierarchy, "Номенклатура");

Report("Element=" + SelectDetails. Номенклатура);

EndCycle;

EndCycle;

В допълнение, платформата позволява, когато се извършва селекция, да се изчислят сумите на всяко ниво, нека вземем сумите от директорията (а не от регистрите за натрупване) за опростяване на заявката:

Заявка = Нова заявка;

Заявка . Text = "SELECT Item.Link AS Item, Nomenclature.Sold AS Sold

ОТ Справочник.Номенклатура КАТО Номенклатура

ОБЩА СУМА (ПРОДАДЕНО)

ЙЕРАРХИЯ на софтуерната номенклатура“;

проба = Искане. Изпълни(). Select(BypassQueryResult.ByGroupingSIhierarchy, "Номенклатура");

Чао Избор. Цикъл Next().

Докладвай ("Група=" + Избор. Артикул+ " Продаден=" + Избор. Продаден);

SelectionDetails = Selection.Select(BypassQueryResult.ByGroupsSIerarchy, "Номенклатура");

Докато SelectionDetails. Цикъл Next().

Докладвай ("Артикул=" + Избор на детайли. Артикул+ " Продаден=" + Изберете детайли. Продаден);

EndCycle;

EndCycle;

Забележка 1: Има друга опция, преминаването „По групиране“, което се различава от йерархичното преминаване по това, че елементите за избор с йерархични суми ще бъдат в него като подробни записи, а не като записи на възли.

Забележка 2: За да преминете през директория с по-сложна структура (брой нива>2), можете да използвате рекурсия, например така:

……………………..

проба = Request.Run(). Изберете (WalkthroughQueryResult.ByGroupingHIerarchy);
SelectRecursively(Select);

………….
Край на процедурата

Процедура SelectRecursively(Select)

Докато Select.Next() цикъл

Докладвай (Мостра. Артикул + "количество=" + Избор. Продаден);

// Опит за получаване на дъщерни записи

SelectRecursively(Selection.Select(WalkingQueryResult.ByGroupsSIerarchy);
EndCycle;
Край на процедурата

Забележка 3: Друга употреба на йерархична извадка е качването на резултати от заявка в обект от типа Дърво на стойностите, например по този начин:

ValueВFormAttributes(Result. Unload(BypassQueryResult.ByGroupingSIerarchy, "Tree" );

Дърво = Резултат. Unload(BypassQueryResult.ByGroupingHIerarchy);

6. Временни таблици, пакетни заявки.

Друга много мощна функция на езика за заявки 1C е работата с временни таблици. По същество ние поставяме резултата от заявката във временна таблица, с която след това можем да работим като с обикновена таблица. Самата заявка се превръща в комбинация от няколко заявки, които се изпълняват строго последователно; една (последна) заявка от пакета извършва извличане на данни - такава съставна заявка се нарича пакетна заявка. Всяка временна таблица има собствено име и т.н. партидната заявка може да създаде произволен брой таблици. Продължителността на живота на временна таблица е ограничена от времето за изпълнение на заявката; веднага щом заявката бъде изпълнена, всички временни таблици се унищожават и паметта, заета от съхраняване на данни от временна таблица, се освобождава.

За да поставите данни във временна таблица, се използва операторът PUT, който се записва в заявката между операторите SELECT и FROM. Заявките в пакетна заявка са разделени една от друга със следните редове:

////////////////////////////////////////////////////////////

Пример за заявка за малка партида, избираща последния документ за продажба „Продажби“ (документът има таблична част„Продукти“, който изброява продадените стоки) за всеки артикул.

Схема на партидна заявка:

при 1 заявка получаваме пълен списък на продаваните артикули и максималната дата за продажба за всеки артикул,

във 2-ра заявка за всеки артикул от първата заявка избираме документ за продажба с дата, равна на максималната за този артикул

ИЗБЕРЕТЕ SalesProducts.Nomenclature, MAXIMUM(SalesProductsProducts.Link.Date) AS Дата

СЛОЖЕТЕ Дати

ОТ Продукти Продажби

ГРУПИРАНЕ ПОПродажба на номенклатура

////////////////////////////////////////////////////////////

ИЗБЕРЕТЕ Dates.Nomenclature, Dates.Date, MAXIMUM(Implementation.Reference) AS Reference

ОТ Фурми КАТО Фурми

ВЪТРЕШНО СЪЕДИНЕНИЕДокумент.Внедряване КАК Внедряване

Софтуерни дати.Дата = Дата на внедряване

ГРУПИРАНЕ ПОВнедряване.Връзка

Какво ви дава използването на пакетни заявки:прави възможно писането на по-сложни заявки и в същото време по-четливи заявки, оптимизира скоростта на изпълнение на заявката, често това е единственият начин да се избегне изпълнението на заявка в цикъл. Ако погледнете източниците типични конфигурации- Всички сложни заявкисе пишат изключително като партидни.

7. Поредица от числа, дати.

Задача: генериране на числова последователност от 0 до 959 в заявка. Когато използвате пакетна заявка, проблемът може да бъде решен лесно:

SELECT Digits.Field1 AS Digit

МЯСТО Числа

ОТ (ИЗБЕРЕТЕ 1 КАТО поле1

КОМБИНИРАЙ ИЗБЕРИ 2

КОМБИНИРАЙ ИЗБЕРИ 3

КОМБИНИРАЙ ИЗБЕРИ 4

КОМБИНИРАЙ ИЗБЕРИ 5

КОМБИНИРАЙ ИЗБЕРИ 6

КОМБИНИРАЙ ИЗБЕРИ 7

КОМБИНИРАЙ ИЗБЕРИ 8

КОМБИНИРАЙ ИЗБЕРИ 9

КОМБИНИРАЙ ИЗБЕРИ 10) КАК ДА ЧИСЛАТА

ИЗБЕРЕТЕ (Цифри.Цифри - 1) + (Цифри1.Цифри - 1)* 10+ (Цифри2.Цифри - 1)* 100 AS номер

WHERE (Цифри.Цифри - 1) + (Цифри1.Цифри - 1)* 10+ (Цифри2.Цифри - 1)* 100<= 959

ПОРЪЧАЙ ПО БРОЙ

Задача: генериране на поредица от дати от Дата1 до Дата2. Решението е подобно, можете да го направите в 3 стъпки (първата и втората, както в примера по-горе, но резултатът не се избира, а се поставя във временна таблица) или в 2 стъпки, като промените втората заявка на пакета на тази :

ИЗБЕРЕТЕ ADDKDATE (&Дата1, ДЕН, (Цифри.Цифри - 1) + (Цифри1.Цифри - 1)* 10+ (Цифри2.Цифри - 1)* 100) AS Дата

ОТ Числа КАТО Числа, Числа КАТО Числа1, Числа КАТО Числа2

КЪДЕ ДА ДОБАВЯ ДАТА (&Дата1, ДЕН, (Цифри.Цифри - 1) + (Цифри1.Цифри - 1)* 10+ (Цифри2.Цифри - 1)* 100)

И след това изпълнете следната заявка:

Забележка: Естествено, тази заявка ще работи правилно само ако няма повече от 999 дни между датите Date1 и Date2.

8. Използване на данни от таблицата със стойности в заявка.

Ако в първия раздел (оператор IN) сравняваме набор от полета с данни от таблицата със стойности, понякога това не е достатъчно. Например набори от данни се предават от източник на трета страна, например: баркод и брой продадени единици. Можете, разбира се, да заобиколите подавания набор от стойности в заявка, като изпълните заявка при всяка итерация на цикъла, но това е най-лошият вариант за решаване на този проблем. По-правилно е да направите това:

1. Създайте въведена таблица със стойности (т.е., която има тип, посочен за всяко поле).

2. Попълнете таблицата със стойности с получените данни за продажбите.

3. Търсене на елементи в заявката.

Примерен код за етапи 1 и 3:

Създаване на въведена таблица със стойности:

// Създаване на типови дескриптори за таблицата със стойности

КЧК = Нови квалификационни числа (14, 3);

КЧШК = Нови квалификационни числа (13, 0);

Array = Нов масив;

Масив . Add(Type("Number" ));

DescriptionTypesCHK = Нов DescriptionTypes(Array, CHK);

Масив . Изчистване();

Масив . Add(Type(" Number"));

DescriptionTypesCHSh = Нов DescriptionTypes(Array, KCHShK);

// Създаване на таблица със стойности

ValueTable = Нова таблица със стойности;

// добавете две колони към таблицата със стойности

Таблица със стойности. Columns.Add("Баркод" , Описание на типа, "Баркод" , 13);

Таблица със стойности. Колони. Add("Продаден", DescriptionTypesCHK, "Продаден", 14);

Заявка = Нова заявка;

Търсене на артикули в заявка:

Request.Text = "ИЗБЕРЕТЕ TK.Баркод, TK.Количество

СЛОЖЕТЕ ТК

////////////////////////////////////////////////////////////////////////////////

ОТ &TK КАТО TK

ИЗБЕРЕТЕ TK.Количество КАТО Обем на продажбите, Номенклатура.Връзка КАТО Връзка

ВЪТРЕШНО СЪЕДИНЕНИЕОТ ТК КАТО ТК

Справочник.Номенклатура AS Номенклатура

Заявка BY TZ.Баркод = Номенклатура.Баркод";

Забележка: . SetParameter("TK", таблица със стойности);

/
За да работите с таблицата със стойности в заявка, винаги трябва първо да поставите данните от таблицата със стойности във временна таблица и едва след това можете да работите с тези данни в пакетна заявка.

Осъществяване на обработка на данни

Подреждане на резултатите от заявката ПОРЪЧАЙТЕ ПО 1.1. Ако алгоритъмът за обработка на резултатите от заявката зависи от реда на записите в заявката или ако резултатът от обработката на заявката в една или друга форма е представен на потребителя, тогава изречението трябва да се използва в текста на заявката ПОРЪЧАЙТЕ ПО. При липса на изразяване

не могат да се правят предположения за реда, в който записите ще се показват в резултатите от заявката.

  • Типични примери за проблеми, които могат да възникнат:
  • различна последователност на редовете в табличния раздел при попълване според резултатите от заявката;
  • различен ред на извеждане на данните (редове, колони) в отчетите;

Вероятността от различни резултати при извършване на едни и същи действия се увеличава

  • при прехвърляне на информационна база към друга СУБД
  • при промяна на версията на СУБД
  • при промяна на параметрите на СУБД

* Забележка: подреждането на резултатите от заявки, които генерират движения, е оправдано само ако подреждането е част от алгоритъма за генериране на движения (например отписване на салдата на партиди стоки с помощта на FIFO). В други случаи записите не трябва да се сортират, тъй като допълнителното подреждане ще създаде прекомерно натоварване на СУБД.

1.2. Ако резултатите от заявка трябва да бъдат показани на потребителя по някакъв начин, тогава

  • необходимо е да се организират резултатите от такива заявки по полета от примитивни типове;
  • Подреждането по полета на референтни типове трябва да бъде заменено с подреждане по низови представяния на тези полета.

В противен случай редът на редовете ще изглежда произволен (необясним) за потребителя.

Вижте също: Сортиране на редове от таблицата със стойности

1.3. Няма оферта ПОРЪЧАЙТЕ ПОоправдано само в случаите, когато

  • алгоритъмът за обработка на резултатите от заявката не разчита на определен ред на записите
  • резултатът от обработката на изпълнената заявка не се показва на потребителя
  • резултатът от заявката очевидно е един запис

Споделено ползване с РАЗЛИЧЕН дизайн

2. Ако заявката използва конструкцията РАЗЛИЧНИ, подреждането трябва да се извършва само по полета, включени в селекцията (в раздела ИЗБЕРЕТЕ).

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

Ограничения при използването на конструкцията AUTO ORDER

3. Използване на дизайна ПЪРВОзаедно със структурата АВТОМАТИЧНА ПОРЪЧКАзабранено.

В други случаи дизайнът АВТОМАТИЧНА ПОРЪЧКАСъщо така не се препоръчва да се използва, тъй като разработчикът не контролира кои полета ще се използват за поръчка. Използването на такъв дизайн е оправдано само в случаите, когато резултантният ред на записите не е важен, но той трябва да бъде един и същ, независимо от използваната СУБД.

Реших да направя своя принос и да опиша тези характеристики на езика, които не бяха обсъдени в горните статии. Статията е насочена към начинаещи разработчици.

1. “IZ” дизайн.

За да получите данни от базата данни, изобщо не е необходимо да използвате конструкцията „ОТ“.
Пример: Трябва да изберем цялата информация за банките от указателя на банките.
Заявка:

ИЗБЕРЕТЕ Директория.Банки.*

Избира всички полета от директорията Банки. И е подобно на искането:

ИЗБЕРЕТЕ Банки.* ОТ Директория.Банки КАТО Банки

2. Подреждане на данни по референтно поле

Когато трябва да организираме данните на заявката по примитивни типове: "Низ", "Число", "Дата" и т.н., тогава всичко се решава с помощта на конструкцията "ORDER BY", ако трябва да подредите данните по референтно поле? Референтното поле е връзка, уникален идентификатор, т.е. Грубо казано, някакъв произволен набор от знаци и обикновено подреждане може да доведе до резултат, който не е напълно очакван. За подреждане на референтни полета се използва конструкцията "AUTO ORDER". За да направите това, първо трябва да подредите данните директно по референтния тип, като използвате конструкцията "ORDER BY", а след това конструкцията "AUTO ORDER".

В този случай за документи подреждането ще се извърши в реда "Дата->Номер", за справочници в "Основен изглед". Ако подреждането не се извършва чрез референтни полета, тогава използването на конструкцията "AUTO ORDER" не се препоръчва.

В някои случаи конструкцията "AUTO ORDER" може да забави процеса на избор. По същия начин можете да пренапишете без автоматично подреждане на документи:

3.Получаване на текстово представяне от референтен тип. Дизайн "ПРЕЗЕНТАЦИЯ".

Когато трябва да покажете поле от референтен тип, например полето "Банка", което е връзка към елемент от директорията "Банки", трябва да разберете, че при показване на това поле, подзаявка към " Banks" ще се изпълни автоматично, за да се получи изглед на директорията. Това ще забави извеждането на данни. За да избегнете това, трябва да използвате конструкцията "PRESENTATION" в заявката, за да получите незабавно представяне на обекта и след това да го покажете за преглед.

В системата за съставяне на данни този механизъм се използва по подразбиране, но когато създавате оформления в клетки, трябва да посочите представянето на референтното поле и например да поставите самата връзка в преписа.

4. Условие за извадка на данните по образец.

Например, трябва да получите мобилни телефони на служители от формата (8 -123- 456-78-912). За да направите това, трябва да зададете следното условие в заявката:

ИЗБЕРЕТЕ Employee.Name, Employee.Phone AS Phone FROM Directory.Employees AS Employees WHERE Телефон LIKE "_-___-___-__-__"

Знакът "_" е служебен знак и замества всеки знак.

5. Едновременно използване на суми и групи.


Общите суми често се използват заедно с групирането; в този случай агрегатните функции може да не са посочени в общите суми.

ИЗБЕРЕТЕ Предоставяне на услуги. Организация КАТО Организация, Предоставяне на услуги. Номенклатура КАТО Номенклатура, SUM(Предоставяне на услуги. Сума на документа) КАТО Сума на документа ОТ Документ. Предоставяне на услуги КАТО Предоставяне на услуги ГРУПИРАНЕ ПО Предоставяне на услуги. Организация, Предоставяне на услугите. Номенклатура РЕЗУЛТАТИ ПО ОБЩИ, Организация, номенклатура

В този случай заявката ще върне почти същото като следната заявка:

ИЗБЕРЕТЕ Предоставяне на услуги. Организация КАТО Организация, Предоставяне на услуги. Номенклатура КАТО Номенклатура, Предоставяне на услуги. Сума на документа КАТО Сума на документа ОТ Документ. Предоставяне на услуги КАТО Предоставяне на услуги РЕЗУЛТАТИ СУМА (Сума на документа) ПО ОБЩО, Организация, Номенклатура

Само първата заявка ще свие записи със същата номенклатура.

6. Дерефериране на полета.

Обръщането към полета чрез точка се нарича операция за дерефериране на референтно поле. например Разплащане.Организация.Административна единица. В този случай в справочното поле "Организация" на документ "Плащане" препраща към друга таблица "Организации", в която ще се получи стойността на атрибута "Административна единица". Важно е да се разбере, че при достъп до полета чрез точка платформата имплицитно създава подзаявка и обединява тези таблици.

Заявка:

Може да се представи като:

ИЗБЕРЕТЕ Плащане.Връзка, Плащане.Организация, Плащане.Организация, Организации. AdministrativeUnit FROM Document.Payment AS Payment LEFT JOIN Directory.Organizations AS Организации Софтуер Payment.Organization = Organisations.Link

При дерефериране на референтни полета от съставен тип, рамката се опитва да създаде имплицитни съединения към всички таблици, които са част от типа на това поле. В този случай заявката няма да бъде оптимална, ако е ясно какъв тип поле е, е необходимо да се ограничат такива полета по тип с конструкция ЕКСПРЕС().

Например има регистър за натрупване „Неразпределени плащания“, където няколко документа могат да действат като регистратор. В този случай е неправилно да се получат стойностите на данните на регистратора по този начин:

ИЗБЕРЕТЕ UnallocatedPayments.Registrar.Date, ..... ОТ RegisterAccumulation.UnallocatedPayments AS UnallocatedPayments

трябва да ограничите типа на съставното поле до logger:

SELECT EXPRESS(UnallocatedPayments.Register AS Document.Payment).Date, ..... FROM RegisterAccumulation.UnallocatedPayments AS UnallocatedPayments

7. Конструкция "КЪДЕ"

При ляво съединение на две таблици, когато наложите условие “WHERE” на дясната таблица, ще получим резултат, подобен на резултата с вътрешно съединение на таблици.

Пример. Необходимо е да се изберат всички Клиенти от Указател Клиенти и за тези клиенти, които имат платежен документ със стойност на атрибута "Организация" = &Организация, да се покаже документът "Плащане", за тези, които нямат, да не се показва.

Резултатът от заявката ще върне записи само за онези клиенти, които са имали плащане от организация в параметъра, и ще филтрира други клиенти. Следователно първо трябва да получите всички плащания за „такава и такава“ организация във временна таблица и след това да я свържете към директорията „Клиенти“, като използвате ляво съединение.

ИЗБЕРЕТЕ Payment.Link AS Payment, Payment.Shareholder AS Client PLACE toPayments FROM Document.Payment AS Payment WHERE Payment.Branch = &Branch; /////////////////////////////////////////////// // /////////////////////////// ИЗБЕРЕТЕ Clients.Link AS Client, ISNULL(tPayment.Payment, "") AS Плащане ОТ Директория .Clients AS Клиенти ЛЯВА ВРЪЗКА topayments AS topayments СОФТУЕР Clients.Link = topayments.Client

Можете да заобиколите това състояние по друг начин. Необходимо е да се наложи условие "WHERE" директно върху връзката между двете таблици. Пример:

ИЗБЕРЕТЕ Clients.Link, Payment.Link FROM Directory.US_Subscribers AS US_Subscribers ЛЯВА ВРЪЗКА Document.Payment AS софтуер за плащане (Clients.Link = Payment.Client И Payment.Client.Name КАТО "Sugar Packet") ГРУПИРАНЕ ПО Clients.Link, Payment. Връзка

8. Съединения с вложени и виртуални таблици

Вложени заявкичесто е необходимо за извличане на данни въз основа на някакво условие. Ако след това ги използвате заедно с други таблици, това може критично да забави изпълнението на заявката.

Например трябва да получим сумата на баланса към текущата дата за някои клиенти.

SELECT UnallocatedPaymentsBalances.Customer, UnallocatedPaymentsBalances.AmountBalance FROM (SELECT Clients.Link AS Link FROM Directory.Clients AS Clients WHERE Clients.Link IN(&Clients)) AS NestedQuery LEFT JOIN RegisterAccumulations.UnallocatedPayments.Balances AS UnallocatedPayments BY Nested nyRe quest.Link = UnallocatedPaymentsBalances. Клиент

При изпълнение на такава заявка оптимизаторът на СУБД може да направи грешки при избора на план, което ще доведе до неоптимално изпълнение на заявката. При свързване на две таблици оптимизаторът на СУБД избира алгоритъм за свързване на таблици въз основа на броя на записите в двете таблици. Ако има вложена заявка, е изключително трудно да се определи броят на записите, които вложената заявка ще върне. Следователно винаги трябва да използвате временни таблици вместо вложени заявки. Така че нека пренапишем заявката.

ИЗБЕРЕТЕ Clients.Link AS Link PLACE tClients FROM Directory.Clients AS Clients WHERE
Clients.Link B (&Клиенти) ; /////////////////////////////////////////////// // /////////////////////////// ИЗБЕРЕТЕ tClients.Link, UnallocatedPaymentsRemains.AmountRemaining, FROM tClients AS tClients LEFT JOIN RegisterAccumulations.UnallocatedPayments.Balances (, Client IN (SELECT tClients. Link FROM tClients)) AS UnallocatedPaymentsBalances tClients.Link = UnallocatedPaymentsBalances.Clients

В този случай оптимизаторът ще може да определи колко записа използва временната таблица tClients и ще може да избере оптималния алгоритъм за свързване на таблици.

Виртуални маси , ви позволяват да получите почти готови данни за повечето приложни задачи (част от първата, част от последната, остатъци, обороти, остатъци и обороти) Ключовата дума тук е виртуална. Тези таблици не са физически, а се съставят от системата в движение, т.е. При получаване на данни от виртуални таблици, системата събира данни от крайните регистърни таблици, композира, групира и ги издава на потребителя.

Тези. При свързване към виртуална таблица се осъществява връзка към подзаявка. В този случай оптимизаторът на СУБД може също да избере неоптимален план за свързване. Ако заявката не се генерира достатъчно бързо и заявката използва съединения във виртуални таблици, тогава се препоръчва да преместите достъпа до виртуалните таблици към временна таблица и след това да направите съединение между две временни таблици. Нека пренапишем предишната заявка.

ИЗБЕРЕТЕ Clients.Link AS Link PLACE tClients FROM Directory.Clients AS Clients INDEX BY Link WHERE
Clients.Link B (&Клиенти) ; /////////////////////////////////////////////// // /////////////////////////// ИЗБЕРЕТЕ UnallocatedPayments.AmountBalance, UnallocatedPayments.Client AS Client PLACE баланси ОТ RegisterAccumulations.UnallocatedPayments.Balances(, Client B ( SELECT tClients Link FROM tClients)) AS UnallocatedPaymentsBalances; /////////////////////////////////////////////// // /////////////////////////// ИЗБЕРЕТЕ tClients.Link, toRemainders.AmountRemaining AS AmountRemaining FROM tClients AS tClients LEFT JOIN toRemainders AS Remainders BY tClients.Link = tRemainings.Client

9. Проверка на резултата от заявката.

Резултатът от заявката може да е празен, използвайте следната конструкция:

ResRequest = Request.Execute(); If resQuery.Empty() Then Return; endIf;

Метод празен()трябва да се използва преди методите Изберете ()или Разтоварване(), тъй като извличането на колекцията отнема време.

За никого не е откровение, че е изключително нежелателно да се използват заявки в цикъл. Това може критично да повлияе на времето за работа на определена функция. Много е желателно да получите всички данни в заявката и след това да ги обработите в цикъл. Но понякога има случаи, когато става невъзможно преместването на заявката извън цикъла. В този случай за оптимизация можете да преместите създаването на заявката извън цикъла и в цикъла да замените необходимите параметри и да изпълните заявката.

Заявка = Нова заявка; Query.Text = "SELECT | Clients.Link, | Clients.BirthDate |FROM | Directory.Clients AS Clients | WHERE | Clients.Link = &Client"; За всеки ред FROM TableClients Loop Query.SetParameter("Клиент", Клиент);

QueryResult = Query.Execute().Select(); EndCycle;

Това ще спаси системата от проверка на синтаксиса на заявката в цикъл.

11. Конструкция "ИМАНЕ".

ИЗБЕРЕТЕ Payment.Customer, AMOUNT(Payment.Amount) AS Amount FROM Document.Payment AS Payment WHERE MONTH(Payment.Date) = 9 GROUP BY Payment.Customer HAVING AMOUNT(Payment.Amount) > 13000

В конструктора, за да направите това, просто отидете в раздела „Условия“, добавете ново условие и поставете отметка в квадратчето „По избор“. Тогава просто пишете Сума(Плащане.Сума) > 13000


12. NULL стойност

Тук няма да описвам принципите на тризначната логика в базата данни; има много статии по тази тема. Само накратко как NULLможе да повлияе на резултата от заявката. Стойността NULL всъщност не е стойност и фактът, че стойността е недефинирана, е неизвестен. Следователно всяка операция с NULL връща NULL, било то събиране, изваждане, деление или сравнение. NULL стойност не може да бъде сравнена с NULL стойност, защото не знаем какво да сравним. Тези. и двете сравнения са: NULL = NULL, NULL<>NULL не е True или False, не е известно.

Нека разгледаме един пример.

За тези клиенти, които нямат плащания, трябва да покажем полето „Подпис“ със стойност „Няма плащания“. Освен това знаем със сигурност, че имаме такива клиенти. И за да отразя същността на това, което написах по-горе, нека го направим по този начин.

ИЗБЕРЕТЕ „Без плащания“ AS Attribute, NULL AS Document PLACE topayments; /////////////////////////////////////////////// // /////////////////////////// ИЗБЕРЕТЕ Clients.Link AS Client, Payment.Link HOW Payment PUT tClientPayment FROM Directory.Clients AS Clients LEFT CONNECTION Document. Payment AS Payment Software Clients.Link = Payment.Shareholder; /////////////////////////////////////////////// // //////////////////////// ИЗБЕРЕТЕ tClientPayment.Client ОТ tClientPayment КАТО tClientPayment ВЪТРЕШНО ПРИСЪЕДИНЯВАНЕ към tPayment КАТО tTopay ОТ tClientPayment.Payment = tPayment

Обърнете внимание на втората временна таблица tClientPayment. С лявото присъединяване избирам всички клиенти и всички плащания за тези клиенти. За тези клиенти, които нямат плащания, полето „Плащане“ ще бъде NULL. Следвайки логиката, в първата временна таблица “tPayments” обозначих 2 полета, едното от тях NULL, а вторият ред “Няма плащания”. В третата таблица свързвам таблиците „tClientPayment“ и „tPayment“, като използвам полетата „Payment“ и „Document“ с вътрешно съединение. Знаем, че в първата таблица полето „Документ“ е NULL, а във втората таблица тези, които нямат плащания в полето „Плащане“ също са NULL. Какво ще ни върне подобна връзка? Но няма да върне нищо. Тъй като сравнението NULL = NULL не се оценява на True.

За да може заявката да върне очаквания резултат, нека я пренапишем:

ИЗБЕРЕТЕ „Без плащания“ AS Attribute, VALUE(Document.Payment.EmptyLink) AS Document PLACE toPayments; /////////////////////////////////////////////// // //////////////////////////// ИЗБЕРЕТЕ Clients.Link AS Client, ISNULL(Payment.Link, VALUE(Document.Payment.EmptyLink )) КАК Плащане PUT tClientPayment FROM Directory.Clients AS Clients LEFT CONNECTION Document.Payment AS Payment BY Clients.Link = Payment.Shareholder; /////////////////////////////////////////////// // //////////////////////// ИЗБЕРЕТЕ tClientPayment.Client ОТ tClientPayment КАТО tClientPayment ВЪТРЕШНО ПРИСЪЕДИНЯВАНЕ към tPayment КАТО tTopay ОТ tClientPayment.Payment = tPayment

Сега във втората временна таблица сме посочили, че ако полето „Плащане“ е NULL, тогава това поле = празна връзка към платежния документ. В първата таблица също заменихме NULL с празна препратка. Сега връзката включва не-NULL полета и заявката ще върне очаквания резултат.

Всички искания, съдържащи се в статията, отразяват ситуациите, които бих искал да разгледам и нищо повече. ЗА Те може да не са заблуди или неоптимални, основното е, че отразяват същността на примера.

13. Недокументирана характеристика на дизайна "ИЗБОР КОГАТО...ТОГДА...КРАЙ".

В случай, че е необходимо да опишем конструкцията „Условия“ в заявката, използваме стандартния синтаксис:

SELECT SELECTION WHEN Users.Name = "Vasya Pupkin" THEN "Нашият любим служител" ELSE "Ние не знаем това" END AS Field1 FROM Directory.Users AS Users

Но какво ще стане, ако например трябва да получим името на месеца в заявка? Писането на огромна конструкция в заявка е грозно и отнема много време, така че тази форма на писане по-горе може да ни помогне:

ИЗБЕРЕТЕ МЕСЕЦ(US_CalculationConsumption_TurnoverSchedule.CalculationPeriod) WHEN 1 THEN "Януари" WHEN 2 THEN "February" WHEN 3 THEN "March" WHEN 4 THEN "April" WHEN 5 THEN "May" WHEN 6 THEN "June" WHEN 7 THEN "July" WHEN 8 ТОГАВА "Август" КОГАТО 9 ТОГАВА "Септември" КОГАТО 10 ТОГАВА "Октомври" КОГАТО 11 ТОГАВА "Ноември" КОГАТО 12 ТОГАВА "Декември" КРАЙ КАТО МЕСЕЦ

Сега дизайнът изглежда по-малко тромав и е лесен за разбиране.

14. Пакетно изпълнение на заявки.


За да не се умножават заявките, можете да създадете една голяма заявка, да я разделите на пакети и да работите с нея.
Например, трябва да получа следните полета от директорията „Потребители“: „Дата на раждане“ и наличните роли за всеки потребител. качете това в различни таблични части на формуляра. Разбира се, можете да направите това с една заявка, след което ще трябва да преминете през записите или да ги свиете, или можете да направите следното:

ИЗБЕРЕТЕ Users.Link AS пълно име, Users.Date of Birth, Users.Role PUT vtUsers FROM Directory.Users AS Users; /////////////////////////////////////////////// // /////////////////////////// ИЗБЕРЕТЕ tueUsers.Пълно име, tueUsers.Дата на раждане ОТ tueUsers КАТО tueUsers ГРУПИРАНЕ ПО tueUsers.пълно име, tueUsers Дата на раждане; /////////////////////////////////////////////// // //////////////////////// ИЗБЕРЕТЕ wUsers.Пълно име, wUsers.Роля ОТ wUsers AS wUsers GROUP BY wUsers.Пълно име, wUsers Дата от раждането

tPackage = Request.ExecutePackage();

TP_BirthDate = tPackage.Upload();
TP_Roles = tPackage.Unload();

Както виждаме, заявката може да бъде изпълнена групово и резултатът да бъде обработен като масив. В някои случаи е много удобно.

15. Условия в пакетна заявка

Например, имаме пакетна заявка, където първо получаваме полетата: „Име, дата на раждане, код“ от директорията „Потребители“ и искаме да получим записи с условия за тези полета от директорията „Лични лица“.

ИЗБЕРЕТЕ Users.Individual.Name AS Име, Users.Individual.Date of Birth AS Дата на раждане, Users.Individual.Code AS Code PLACE vtUsers FROM Directory.Users AS Users; /////////////////////////////////////////////// // ///////////////////// ИЗБЕРЕТЕ ЛИЦА КАТО ФИЗИЧЕСКИ ЛИЦА ОТ Директория

Можете да наложите такива условия:

WHERE Individuals.Code IN (SELECT tueUsers.Code FROM tueUsers) И Individuals.Name IN (SELECT tueUsers.Code FROM tueUsers) AND Individuals.BirthDate IN (SELECT tueUsers.DateBirth FROM tueUsers)

И можете да го направите така:

WHERE (Individuals.Code, Individuals.Name, Individuals.Date of Birth) IN (ИЗБЕРЕТЕ tueUsers.Code, tueUsers.Name, tueUsers.Дата на раждане ОТ tueUsers)

Освен това е необходимо да се поддържа ред.

16. Извикване на конструктора на заявки за „условие“ в групова заявка

Когато е необходимо да се наложи условие, както в примера по-горе, можете да забравите как се извиква това или онова поле във виртуалната таблица.
Например, трябва да поставите условие в полето "Дата на раждане", а във виртуалната таблица това поле се нарича "Дата на раждане на длъжника" и ако забравите името, ще трябва да излезете от редактирането на условието без запазване и вижте името на полето. За да избегнете това, можете да използвате следната техника.

Необходимо е да поставите скоби след конструкцията „B“ и да оставите празно пространство (интервал) между скобите, да изберете това пространство и да извикате конструктора на заявката. Дизайнерът ще има достъп до всички таблици на груповата заявка. Техниката работи както на виртуални регистрационни таблици, така и на раздела „Условия“. В последния случай трябва да поставите отметка в квадратчето „P (произволно условие)“ и да влезете в режим на редактиране „F4“.

Заявките често бяха измислени в движение и те просто служат за илюстрация на „техниките“, които обмислях.

Исках да разгледам използването на индекси в заявки, но това е много обширна тема. Ще го поставя в отделна статия или ще го добавя тук по-късно.

upd1. Точки 11,12
upd2. Точки 13,14,15,16

Използвана литература:
Език за заявки "1C:Enterprise 8" - E.Yu. Хрусталева
Професионално развитие в системата 1C:Enterprise 8."