Минимализмы 3

19.02.18

Разработка - Математика и алгоритмы

Очередная серия "минимализмов" [http://infostart.ru/public/306536/, https://infostart.ru/public/460935/]. Также, как и в предыдущих статьях, здесь приведена подборка коротких оригинальных авторских решений некоторых задач. Ранее эти решения были разбросаны по моим комментариям к чужим публикациям.

Содержание:

72. Очистка строки от нецифровых символов 
71. Определение суммарного покрытия перекрывающихся интервалов 
70. Определение пересечения интервалов в кольце 
69. Быстрое удаление строк в таблице значений 
68. Получение интервалов неизменности курсов валют 
67. Определение пропусков в последовательности чисел 
66. Инвертирование периодов в запросе 
65. Проверка совпадения таблиц 
64. Проверка совпадения таблиц путем сравнения полного и внутреннего соединения 
63. Получение списка простых чисел в запросе 
62. Определение периодов работы сотрудников по данным СКУД 
61. Найти документы, во всех строках которых колонка количество меньше либо равна нулю 
60. Определение плановых остатков товара с учетом предшествующих фактических и будущих плановых продаж 
59. Сравнение плановых и фактических дней отпуска 
58. Получить дату по номеру дня недели и его порядковому номеру в месяце 
57. Получение предпоследнего курса валюты 
56. Определить элементарные интервалы, образующиеся при пересечении всех исходных интервалов 
55. Найти количество записей, повторяющихся подряд несколько дней 
54. Сравнение набора товаров, проданных сменами 
53. Найти документ, состав табличной части которого соответствует параметру - таблице значений 
52. Распределение товаров по ячейкам в запросе 
51. Объединение пересекающихся периодов в запросе 
50. Выделение разрядов числа без использования округления и деления по модулю 
49. Посчитать запросом суммарную длительность различных состояний 
48. Разбиение произвольного периода на интервалы в запросе 
47. Поиск свободного штрихкода внутри одного префикса 
46. Выбор записи по номеру из НЕПРОНУМЕРОВАННОЙ таблицы 
45. Как в запросе секунды преобразовать в часы и минуты 
44. Убрать префикс и лидирующие нули из номера 
43. Перебор всех строковых комбинаций "0" и "1" в порядке возрастания числа единиц ("00000"->"00001"->"00010"-> ..."01011"...) 
42. Транслитерация в запросе 
41. Заполнение пропусков в таблице цветов 
40. Количество дней недели (понедельников/вторников/...) в заданном диапазоне запросом 
39. Свернуть строки в таблице значений конкатенацией

 

72. Очистка номера телефона от "мусора" (нецифровых символов)

Ускорить код?

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

В платформе 8.3.6 появились функции СтрРазделить и СтрСоединить, которые позволяют решить эту задачу в одну строку без цикла:

СтрСоединить(СтрРазделить(СтрокаСЦифрами, СтрСоединить(СтрРазделить(СтрокаСЦифрами, "0123456789"))))

 Если список ненужных символов известен, например, "(", ")" и "-", то выражение может быть еще короче:

СтрСоединить(СтрРазделить(СтрокаСЦифрами, "()-"))

 Очевидно, что данный прием легко обобщается на фильтрацию или отбор любого набора символов.

71. Определение суммарного покрытия перекрывающихся интервалов

За период получить количество дней, в которые проходило хотя бы одно мероприятие

Еще одна задача на интервалы (Gaps and Islands Problem). Имеется множество интервалов времени "занятости" помещений, оборудования, других ресурсов. Интервалы могут произвольным образом перекрываться. Требуется определить общее время занятости ресурсов.

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

Оказывается, что воспользовавшись идеями статьи "Расчет средних по периодам в запросе - это элементарно!", можно исключить необходимость второго соединения, поскольку суммарная занятость может быть определена как сумма расстояний до правого края "островов" минус сумма расстояний до левого края островов без необходимости определения длины каждого острова.

Если исходные интервалы  заданы в таблице "Дано" с колонками "ДатаНачала" и "ДатаОкончания", то общее время  занятости ресурсов в днях можно получить следующим достаточно простым запросом:

ВЫБРАТЬ
    СУММА(ВложенныйЗапрос.Разность) КАК ЗанятыхДней
ИЗ
    (ВЫБРАТЬ РАЗЛИЧНЫЕ
        1 - РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), Дано.ДатаНачала, ДЕНЬ) КАК Разность
    ИЗ
        Дано КАК Дано
            ЛЕВОЕ СОЕДИНЕНИЕ Дано КАК Левее
            ПО (Левее.ДатаНачала < Дано.ДатаНачала)
                И Дано.ДатаНачала <= Левее.ДатаОкончания
    ГДЕ
        Левее.ДатаНачала ЕСТЬ NULL

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ РАЗЛИЧНЫЕ
        РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), Дано.ДатаОкончания, ДЕНЬ)
    ИЗ
        Дано КАК Дано
            ЛЕВОЕ СОЕДИНЕНИЕ Дано КАК Правее
            ПО (Правее.ДатаНачала <= Дано.ДатаОкончания)
                И Дано.ДатаОкончания < Правее.ДатаОкончания
    ГДЕ
        Правее.ДатаОкончания ЕСТЬ NULL) КАК ВложенныйЗапрос

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

Если занятость требуется измерять не в днях, а в часах, минутах, секундах и тому подобное, достаточно изменить параметр в функции "РазностьДат".

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

70. Определение пересечения интервалов в кольце

Вычисление пересекающихся интервалов в линейных и замкнутых пространствах имен

Пусть есть две смены: одна с 20:00 до 8: 00, а вторая с 6:00 до 18:00. Пересекаются ли они? Ответ на данный конкретный вопрос вроде бы вполне очевиден, а вот сформулировать общее правило оказывается совсем не так просто.

В результате  запрос, выбирающий смены, пересекающиеся с интервалом времени, заданными переменными @start  и @end, выглядит вот так:

select * from tab
where (@start - start) * (start - @end) * (@start - @end) <= 0 
      or (@start - start) * (@start - end) * (start - end) >= 0;

Это запрос на языке SQL. Для языка запросов 1С время начала и окончания смен потребуется заранее перевести в числовой тип (например, секунды) или использовать встроенную функцию языка запросов "РАЗНОСТЬДАТ".

Данный прием основан на эмуляции логического выражения XOR арифметическим произведением с оценкой знака получившегося результата. 

69. Быстрое удаление строк в таблице значений

Удаление строк в таблице значений

Быстрее всего удаляются строки путем копирования оставшихся строк по условию, обратному к условию удаления:

РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению", Ложь))

68. Получение интервалов неизменности курсов валют

Запрос по курсам валют

ВЫБРАТЬ
    Дано.Период,
    Дано.Валюта,
    Дано.Курс,
    КОЛИЧЕСТВО(Было.Курс) КАК Номер
ПОМЕСТИТЬ Интервалы
ИЗ
    Дано КАК Дано
        ЛЕВОЕ СОЕДИНЕНИЕ Дано КАК Было
        ПО (Было.Валюта = Дано.Валюта)
            И (Было.Период <= Дано.Период)
            И (Было.Курс <> Дано.Курс)
СГРУППИРОВАТЬ ПО
    Дано.Период,
    Дано.Валюта,
    Дано.Курс
;
ВЫБРАТЬ
    МИНИМУМ(Интервалы.Период) КАК ДатаС,
    МАКСИМУМ(Интервалы.Период) КАК ДатаПо,
    Интервалы.Валюта,
    Интервалы.Курс
ИЗ
    Интервалы КАК Интервалы
СГРУППИРОВАТЬ ПО
    Интервалы.Валюта,
    Интервалы.Курс,
    Интервалы.Номер
УПОРЯДОЧИТЬ ПО
    Интервалы.Валюта,
    ДатаС

Как и в других подобных задачах, в этой ключ к решению - в выборе подходящего инварианта. Здесь инвариантом является количество отличающихся курсов перед данным.

Запрос составлялся без оглядки на эффективность. Если данных много и эффективность важна, то можно взять метод решения из http://catalog.mista.ru/public/402534/ . 

67. Определение пропусков в последовательности чисел

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

В обсуждении много разных вариантов решения. Из моих быстрее всего работает вот этот:

ВЫБРАТЬ ПЕРВЫЕ 2
    Дано.Х + ВЗ.У КАК Х
ИЗ
    Дано КАК Дано,
    (ВЫБРАТЬ
        0 КАК У    
    ОБЪЕДИНИТЬ
    ВЫБРАТЬ
        1) КАК ВЗ
СГРУППИРОВАТЬ ПО
    Дано.Х + ВЗ.У
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) = 1
УПОРЯДОЧИТЬ ПО
    Дано.Х + ВЗ.У

В первой строке всегда 0, во второй нужное значение.

66. Инвертирование периодов в запросе

"Вывернуть" периоды в запросе

Есть запрос с выборкой периодов исключения: ДатаНачалаИсключения - ДатаОкончанияИсключения, а также основной период ДатаНачалаОсновная - ДатаОкончанияОсновная. Нужно составить запрос так, чтобы образовались периоды на основании основного периода, в которые не входят периоды исключения.

Вот решение:

ВЫБРАТЬ
    &ДатаНачалаОсновная КАК Дата
ПОМЕСТИТЬ Даты
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(Дано.ДатаНачалаИсключения, ДЕНЬ, -1)
ИЗ
    Дано КАК Дано
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(Дано.ДатаОкончанияИсключения, ДЕНЬ, 1)
ИЗ
    Дано КАК Дано
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    &ДатаОкончанияОсновная
;
ВЫБРАТЬ
    МИНИМУМ(Даты.Дата) КАК ДатаНачала,
    МАКСИМУМ(Даты.Дата) КАК ДатаОкончания
ИЗ
    (ВЫБРАТЬ
        КОЛИЧЕСТВО(Раньше.Дата) КАК Номер,
        Даты.Дата КАК Дата
    ИЗ
        Даты КАК Раньше
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ Даты КАК Даты
            ПО Раньше.Дата <= Даты.Дата
    СГРУППИРОВАТЬ ПО
        Даты.Дата) КАК Даты
СГРУППИРОВАТЬ ПО
    ВЫРАЗИТЬ(Даты.Номер / 2 КАК ЧИСЛО(10, 0))

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

65. Проверка совпадения таблиц

полное совпадение таблиц

Есть массив А из элементов некоторого справочника и есть справочник Б с табличной частью  из элементов того же справочника. Найти элемент Б, где список точно совпадает с массивом А (ни больше ни меньше).

На примере справочника "Контрагенты" (Как справочник Б). Приведенным далее запросом находятся контрагенты, у которых в табличной части имеются менеджеры из справочника "Пользователи" (Справочник А), список которых точно определен массивом &Массив. Требуется заранее определить размер массива и передать его в параметр &МассивКоличество.

ВЫБРАТЬ
	Менеджеры.Ссылка
ИЗ
	Справочник.Контрагенты.МенеджерыПокупателя КАК Менеджеры

СГРУППИРОВАТЬ ПО
	Менеджеры.Ссылка

ИМЕЮЩИЕ
	КОЛИЧЕСТВО(*) = &МассивКоличество И
	МИНИМУМ(Менеджеры.МенеджерПокупателя В (&Массив)) = ИСТИНА

64. Проверка совпадения таблиц путем сравнения полного и внутреннего соединения

ВЫБРАТЬ
	Товары.Номенклатура,
	Товары.Количество
ПОМЕСТИТЬ Эталон
ИЗ
	&Товары КАК Товары
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	Товары.Ссылка
ИЗ
	Документ.ЗаказПокупателя.Товары КАК Товары
		ПОЛНОЕ СОЕДИНЕНИЕ Эталон КАК Эталон
		ПО Товары.Номенклатура = Эталон.Номенклатура
			И Товары.Количество = Эталон.Количество

СГРУППИРОВАТЬ ПО
	Товары.Ссылка

ИМЕЮЩИЕ
	КОЛИЧЕСТВО(Товары.Номенклатура) МЕЖДУ КОЛИЧЕСТВО(*) И КОЛИЧЕСТВО(Эталон.Номенклатура)

Это более простой вариант сравнения таблиц с эталоном, чем, например, в 53. Здесь используется тот факт, что КОЛИЧЕСТВО(*) показывает общее количество строк полного соединения, а КОЛИЧЕСТВО(Товары.Номенклатура) и КОЛИЧЕСТВО(Эталон.Номенклатура) только число строк не ЕСТЬNULL. При совпадении таблиц все эти количества должны быть равны, что и проверяется самым коротким способом с использованием тернарного логического условия МЕЖДУ.

63. Получение списка простых чисел в запросе

Как получить список простых чисел в запросе

 

Вот такой запрос находит все нечетные простые числа на отрезке [1 ... 131073] за 1,308 сек. Используется решето Сундарама. Параметрами является N, которое задает интервал поиска как [1 ... 2N+1] и заранее вычисленное значение (SQRT(2N+1)-1)/2.
-------------------------------------------------------------------------------------------------
ВЫБРАТЬ
0 КАК Х
ПОМЕСТИТЬ Регистр1
ОБЪЕДИНИТЬ
ВЫБРАТЬ
1
;
ВЫБРАТЬ
Младшие.Х + 2 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр2
ИЗ
Регистр1 КАК Младшие,
Регистр1 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 4 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр4
ИЗ
Регистр2 КАК Младшие,
Регистр2 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 16 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр8
ИЗ
Регистр4 КАК Младшие,
Регистр4 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 256 * Старшие.Х + 1 КАК Х
ПОМЕСТИТЬ Регистр16
ИЗ
Регистр8 КАК Младшие,
Регистр8 КАК Старшие
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
2 * ВложенныйЗапрос.Х + 1 КАК ПростоеЧисло
ИЗ
(ВЫБРАТЬ
А.Х + Б.Х + 2 * А.Х * Б.Х КАК Х
ИЗ
Регистр16 КАК А
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Регистр16 КАК Б
ПО (Б.Х МЕЖДУ А.Х И (&Эн - А.Х) / (2 * А.Х + 1))
ГДЕ
А.Х <= &КореньИз_ДваЭнПлюс1_Минус1_РазделитьНа2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
А.Х
ИЗ
Регистр16 КАК А
ГДЕ
А.Х <= &Эн) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
ВложенныйЗапрос.Х

ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) = 1

УПОРЯДОЧИТЬ ПО
ПростоеЧисло
-------------------------------------------------------------------------------------------------
Первая часть запроса, формирующая ряд чисел, взята отсюда: "Порождающий запрос" [//infostart.ru/public/90367/].

"Все нечетные простые числа" означает, что к результату (к полученному множеству простых чисел) нужно добавить единственное простое четное число 2.

Простейший метод перебора с проверкой делимости реализуется так:
--------------------------------------------------------------------------------------------------
ВЫБРАТЬ
Числа.НатуральноеЧисло КАК Х,
Числа.НатуральноеЧисло * Числа.НатуральноеЧисло КАК ХХ
ПОМЕСТИТЬ ВТ
ИЗ
&Числа КАК Числа
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Делимое.Х КАК ПростоеЧисло
ИЗ
ВТ КАК Делимое
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ КАК Делитель
ПО Делимое.Х >= Делитель.ХХ
И ((ВЫРАЗИТЬ(Делимое.Х / Делитель.Х КАК ЧИСЛО(19, 0))) = Делимое.Х / Делитель.Х)

СГРУППИРОВАТЬ ПО
Делимое.Х

ИМЕЮЩИЕ
КОЛИЧЕСТВО(*) = 1
-------------------------------------------------------------------------------------------------
Реализация решета Аткина:
-------------------------------------------------------------------------------------------------
ВЫБРАТЬ
0 КАК Х
ПОМЕСТИТЬ Регистр1

ОБЪЕДИНИТЬ

ВЫБРАТЬ
1
;
ВЫБРАТЬ
Младшие.Х + 2 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр2
ИЗ
Регистр1 КАК Младшие,
Регистр1 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 4 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр4
ИЗ
Регистр2 КАК Младшие,
Регистр2 КАК Старшие
;
ВЫБРАТЬ
Младшие.Х + 16 * Старшие.Х КАК Х
ПОМЕСТИТЬ Регистр8
ИЗ
Регистр4 КАК Младшие,
Регистр4 КАК Старшие
;
ВЫБРАТЬ
1 + Младшие.Х + 256 * Старшие.Х КАК Х
ПОМЕСТИТЬ Ряд
ИЗ
Регистр8 КАК Младшие,
Регистр2 КАК Старшие
ГДЕ
1 + Младшие.Х + 256 * Старшие.Х <= &КореньИзГраницы
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
КвадратичныеФормы.Х,
КвадратичныеФормы.Х * КвадратичныеФормы.Х КАК ХХ
ПОМЕСТИТЬ Кандидаты
ИЗ
(ВЫБРАТЬ
Случай1.Х КАК Х
ИЗ
(ВЫБРАТЬ
4 * А.Х * А.Х + Б.Х * Б.Х КАК Х
ИЗ
Ряд КАК А,
Ряд КАК Б) КАК Случай1
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, Случай1.Х * 5)) В (5, 25)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
Случай2.Х
ИЗ
(ВЫБРАТЬ
3 * А.Х * А.Х + Б.Х * Б.Х КАК Х
ИЗ
Ряд КАК А,
Ряд КАК Б) КАК Случай2
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, Случай2.Х * 5)) = 35

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
Случай3.Х
ИЗ
(ВЫБРАТЬ
3 * А.Х * А.Х - Б.Х * Б.Х КАК Х
ИЗ
Ряд КАК А
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Ряд КАК Б
ПО А.Х > Б.Х) КАК Случай3
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, Случай3.Х * 5)) = 55) КАК КвадратичныеФормы
ГДЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, КвадратичныеФормы.Х * 12)) > 0
И КвадратичныеФормы.Х <= &Граница

СГРУППИРОВАТЬ ПО
КвадратичныеФормы.Х

ИМЕЮЩИЕ
СЕКУНДА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, КОЛИЧЕСТВО(*) * 30)) = 30
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Делимое.Х КАК Х
ИЗ
Кандидаты КАК Делимое
ЛЕВОЕ СОЕДИНЕНИЕ Кандидаты КАК Делитель
ПО (Делитель.ХХ <= Делимое.Х)
И ((ВЫРАЗИТЬ(Делимое.Х / Делитель.Х КАК ЧИСЛО(15, 0))) = Делимое.Х / Делитель.Х)
ГДЕ
Делитель.Х ЕСТЬ NULL

ОБЪЕДИНИТЬ

ВЫБРАТЬ
2

ОБЪЕДИНИТЬ

ВЫБРАТЬ
3

ОБЪЕДИНИТЬ

ВЫБРАТЬ
5

УПОРЯДОЧИТЬ ПО
Делимое.Х
-------------------------------------------------------------------------------------------------
для сравнения. Тут вроде бы нечего дальше оптимизировать, а работает примерно в 1,6 раза дольше, чем Сундарама, который еще можно чуть-чуть "подкрутить" в плане оптимизации (за счет проверки пустых мест рядом с четными, а не соединением с таблицей чисел). Это странно. Алгоритм Аткина вообще-то считается более быстрым.

Тем, кто заинтересовался данной темой, рекомендую статью "Черпаем простые числа решетом Аткина" [//infostart.ru/public/724574/]. Ее автор предложил более быструю (по его словам) реализацию решета Аткина.

62. Определение периодов работы сотрудников по данным СКУД

Сгруппировать периоды в запросе 

В задаче требовалось по данным записи событий входа и выхода на разных дверях предприятия определить периоды работы сотрудника. Дополнительно считается, что если человек в течении 6 часов отсутсвует на территории - то он ушел домой и данный рабочий "день" для него закончен.

Решение можно реализовать вот таким запросом:

ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(ПроходыСигур.Период, СЕКУНДА, РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), ПроходыСигур.Время, СЕКУНДА)) КАК Дата,
    ПроходыСигур.Сотрудник
ПОМЕСТИТЬ Дано
ИЗ
    ПроходыСигур КАК ПроходыСигур
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    МАКСИМУМ(Раньше.Дата) КАК От,
    Дано.Дата КАК До,
    Дано.Сотрудник
ПОМЕСТИТЬ Отсутствия
ИЗ
    Дано КАК Раньше
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Дано КАК Дано
        ПО Раньше.Сотрудник = Дано.Сотрудник
            И Раньше.Дата < Дано.Дата

СГРУППИРОВАТЬ ПО
    Дано.Сотрудник,
    Дано.Дата

ИМЕЮЩИЕ
    РАЗНОСТЬДАТ(МАКСИМУМ(Раньше.Дата), Дано.Дата, ЧАС) > 6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ РАЗЛИЧНЫЕ
    &ДатаНачала,
    &ДатаНачала,
    ПроходыСигур.Сотрудник
ИЗ
    ПроходыСигур КАК ПроходыСигур

ОБЪЕДИНИТЬ

ВЫБРАТЬ РАЗЛИЧНЫЕ
    &ДатаОкончания,
    &ДатаОкончания,
    ПроходыСигур.Сотрудник
ИЗ
    ПроходыСигур КАК ПроходыСигур
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    МАКСИМУМ(Раньше.До) КАК От,
    Отсутствия.От КАК До,
    Отсутствия.Сотрудник
ИЗ
    Отсутствия КАК Отсутствия
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Отсутствия КАК Раньше
        ПО Отсутствия.Сотрудник = Раньше.Сотрудник И Раньше.До < Отсутствия.От  

СГРУППИРОВАТЬ ПО
    Отсутствия.От,
    Отсутствия.Сотрудник

Эта задача тоже относится к классу "Islands and Gaps". В запросе сначала определяются все отсутствия сотрудника, а затем периоды между отсутствиями считаются периодами работы. 
Отсутствиями считаются все периоды неактивности длиннее шести часов. 

То есть предлагается вообще отказаться от анализа типов событий: вход, выход, так как непонятно внешние ли это двери и всегда ли срабатывает регистрация. Любое событие считается активностью. Время соединяется с датой. Это важно для круглосуточности. 

Если все же двери строго внешние и жалко терять информацию о типе события, то "математически" правильно будет разделять последовательные вход-вход или выход-выход противоположным событием, расположенным строго посередине интервала равновероятности времени. В среднем это будет сводить к минимуму ошибку домысливания пропущенного при регистрации события.

61. Найти заказы, количества во всех строках которых меньше либо равны нулю

Нужен алгоритм запроса для получения групп данных с условием, отвечающим элементам подгрупп

ВЫБРАТЬ
Ссылка
ИЗ Документ.ЗаказПокупателя.Товары
СГРУППИРОВАТЬ ПО Ссылка
ИМЕЮЩИЕ МАКСИМУМ(Количество) <= 0

60. Определение плановых остатков товара с учетом предшествующих фактических и будущих плановых продаж

Подскажите с расчетом таблиц в запросе

ВЫБРАТЬ
    ФактическиеПродажи.Период,
    ФактическиеПродажи.Номенклатура,
    ФактическиеПродажи.КоличествоОборот КАК Количество,
    ЛОЖЬ КАК План
ПОМЕСТИТЬ НедельныеПродажи
ИЗ
    РегистрНакопления.Продажи.Обороты(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, НЕДЕЛЯ, -&Окно), НЕДЕЛЯ), КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, НЕДЕЛЯ, -1), НЕДЕЛЯ), Неделя, ) КАК ФактическиеПродажи

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ПланируемыеПродажи.Период,
    ПланируемыеПродажи.Номенклатура,
    ПланируемыеПродажи.КоличествоОборот,
    ИСТИНА
ИЗ
    РегистрНакопления.ПланыПродаж.Обороты(НАЧАЛОПЕРИОДА(&Дата1, НЕДЕЛЯ), &Дата2, Неделя, ) КАК ПланируемыеПродажи
;
ВЫБРАТЬ
    НедельныеПродажи.Период,
    НедельныеПродажи.Номенклатура,
    СРЕДНЕЕ(ПродажиВОкнеНедель.Количество) КАК Расход
ПОМЕСТИТЬ СреднеНедельныеПродажи
ИЗ
    НедельныеПродажи КАК НедельныеПродажи
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ НедельныеПродажи КАК ПродажиВОкнеНедель
        ПО (НедельныеПродажи.План)
            И НедельныеПродажи.Номенклатура = ПродажиВОкнеНедель.Номенклатура
            И (ПродажиВОкнеНедель.Период МЕЖДУ ДОБАВИТЬКДАТЕ(НедельныеПродажи.Период, НЕДЕЛЯ, -&Окно) И НедельныеПродажи.Период)

СГРУППИРОВАТЬ ПО
    НедельныеПродажи.Период,
    НедельныеПродажи.Номенклатура
;
ВЫБРАТЬ
    Периоды.Период,
    ТоварыНаСкладахОстатки.Номенклатура,
    ТоварыНаСкладахОстатки.КоличествоОстаток - СУММА(Расходы.Расход) КАК ПлановыйОстаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(НАЧАЛОПЕРИОДА(&Дата1, НЕДЕЛЯ), ) КАК ТоварыНаСкладахОстатки
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ СреднеНедельныеПродажи КАК Периоды
        ПО ТоварыНаСкладахОстатки.Номенклатура = Периоды.Номенклатура
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ СреднеНедельныеПродажи КАК Расходы
        ПО (Периоды.Номенклатура = Расходы.Номенклатура)
            И (Расходы.Период <= Периоды.Период)

СГРУППИРОВАТЬ ПО
    Периоды.Период,
    ТоварыНаСкладахОстатки.Номенклатура,
    ТоварыНаСкладахОстатки.КоличествоОстаток

59. Сравнение плановых и фактических дней отпуска

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

Имеется график отпусков, в нем есть колонки плановая дата ухода в отпуск и фактическая (эти данные получаются из разных регистров). Необходимо сопоставить эти данные в запросе.

План и факт отпуска рассматриваются как списание по партиям. Запланированный отпуск добавляет неотгулянные дни, а фактический - их списывает. Поэтому критерием соединения плановых и фактических отпусков является сквозной (по всем отпускам) номер дня отпуска. Исходными являются таблицы "План" и "Факт" с колонками "Сотрудник", "Начало", "Окончание".

В обсуждении приведены два варианта решения. Здесь более короткий: 

ВЫБРАТЬ
    План.Сотрудник,
    План.Начало,
    Календарь.ДатаКалендаря КАК День
ПОМЕСТИТЬ ПланДни
ИЗ
    План КАК План
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
        ПО (Календарь.ДатаКалендаря МЕЖДУ План.Начало И План.Окончание)
;

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

ВЫБРАТЬ
    Факт.Сотрудник,
    Факт.Начало,
    Календарь.ДатаКалендаря КАК День
ПОМЕСТИТЬ ФактДни
ИЗ
    Факт КАК Факт
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
        ПО (Календарь.ДатаКалендаря МЕЖДУ Факт.Начало И Факт.Окончание)
;

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

ВЫБРАТЬ
    План.Сотрудник,
    План.Начало,
    План.День,
    КОЛИЧЕСТВО(Прошлое.День) КАК НомерДня
ПОМЕСТИТЬ ПланПлюс
ИЗ
    ПланДни КАК План
        ЛЕВОЕ СОЕДИНЕНИЕ ПланДни КАК Прошлое
        ПО План.Сотрудник = Прошлое.Сотрудник
            И План.День >= Прошлое.День

СГРУППИРОВАТЬ ПО
    План.Сотрудник,
    План.Начало,
    План.День
;

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

ВЫБРАТЬ
    Факт.Сотрудник,
    Факт.Начало,
    Факт.День,
    КОЛИЧЕСТВО(Прошлое.День) КАК НомерДня
ПОМЕСТИТЬ ФактПлюс
ИЗ
    ФактДни КАК Факт
        ЛЕВОЕ СОЕДИНЕНИЕ ФактДни КАК Прошлое
        ПО Факт.Сотрудник = Прошлое.Сотрудник
            И Факт.День >= Прошлое.День

СГРУППИРОВАТЬ ПО
    Факт.Сотрудник,
    Факт.Начало,
    Факт.День
;

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

ВЫБРАТЬ
    ПланПлюс.Сотрудник КАК СотрудникПлан,
    МИНИМУМ(ПланПлюс.День) КАК НачалоПлан,
    МАКСИМУМ(ПланПлюс.День) КАК ОкончаниеПлан,
    ФактПлюс.Сотрудник КАК СотрудникФакт,
    МИНИМУМ(ФактПлюс.День) КАК НачалоФакт,
    МАКСИМУМ(ФактПлюс.День) КАК ОкончаниеФакт,
    ЕСТЬNULL(КОЛИЧЕСТВО(ПланПлюс.День), КОЛИЧЕСТВО(ФактПлюс.День)) КАК Длина
ИЗ
    ПланПлюс КАК ПланПлюс
        ПОЛНОЕ СОЕДИНЕНИЕ ФактПлюс КАК ФактПлюс
        ПО ПланПлюс.Сотрудник = ФактПлюс.Сотрудник
            И ПланПлюс.НомерДня = ФактПлюс.НомерДня

СГРУППИРОВАТЬ ПО
    ПланПлюс.Сотрудник,
    ФактПлюс.Сотрудник,
    ПланПлюс.Начало,
    ФактПлюс.Начало

УПОРЯДОЧИТЬ ПО
    СотрудникПлан,
    НачалоПлан,
    НачалоФакт

58. Получить дату по номеру дня недели и его порядковому номеру в месяце

Получение даты, зная день недели и его порядок в месяце

Иногда бывает необходимость получить "Первый понедельник месяца" или "Вторую пятницу месяца"...

Вот функция для решения этой задачи:

Функция ПолучитьДатуПоНомерамДняВНеделеИМесяце(НомерДняНеделиМесяца, НомерДняНедели, ДатаМесяца)
    
    Возврат НачалоМесяца(ДатаМесяца) 
+ 86400 * (7 * НомерДняНеделиМесяца - 7 + (НомерДняНедели - ДеньНедели(НачалоМесяца(ДатаМесяца)) + 7) % 7)
    
КонецФункции

57. Получение предпоследнего курса валюты

Регистр Сведений

Для одной конкретной валюты будет работать такой вариант:

ВЫБРАТЬ ПЕРВЫЕ 1
    ВЗ.Период КАК Период,
    ВЗ.Курс КАК Курс
ИЗ
    (ВЫБРАТЬ ПЕРВЫЕ 2
        КурсыВалют.Период КАК Период,
        КурсыВалют.Курс КАК Курс
    ИЗ
        РегистрСведений.КурсыВалют КАК КурсыВалют
    ГДЕ
        КурсыВалют.Валюта = &Валюта
    УПОРЯДОЧИТЬ ПО
        Период УБЫВ) КАК ВЗ
УПОРЯДОЧИТЬ ПО
    Период

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

Запросом выделить пересечения интервалов времени в отдельные интервалы

Есть таблица ГрафикПоКалендарю с колонками От, До, ТипВремени и таблица Загрузка с колонками От, До, Работа. Требуется объединить эти таблицу в одну.

Вот решение:

ВЫБРАТЬ
    0 КАК Момент
ПОМЕСТИТЬ ОсьВремени

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    График.От
ИЗ
    ГрафикПоКалендарю КАК График

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    График.До
ИЗ
    ГрафикПоКалендарю КАК График

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Загрузка.От
ИЗ
    Загрузка КАК Загрузка

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Загрузка.До
ИЗ
    Загрузка КАК Загрузка

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    24
;
ВЫБРАТЬ
    ОсьВремени.Момент КАК От,
    МИНИМУМ(Позже.Момент) КАК До
ПОМЕСТИТЬ ВсеИнтервалы
ИЗ
    ОсьВремени КАК ОсьВремени
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ОсьВремени КАК Позже
        ПО ОсьВремени.Момент < Позже.Момент
СГРУППИРОВАТЬ ПО
    ОсьВремени.Момент
;
ВЫБРАТЬ
    ВсеИнтервалы.От,
    ВсеИнтервалы.До,
    ЕСТЬNULL(ГрафикПоКалендарю.ТипВремени, "нераб. время") КАК ТипВремени,
    ЕСТЬNULL(Загрузка.Работа, "без работы") КАК Работа
ИЗ
    ВсеИнтервалы КАК ВсеИнтервалы
        ЛЕВОЕ СОЕДИНЕНИЕ ГрафикПоКалендарю КАК ГрафикПоКалендарю
        ПО (ГрафикПоКалендарю.От <= ВсеИнтервалы.От)
            И ВсеИнтервалы.До <= ГрафикПоКалендарю.До
        ЛЕВОЕ СОЕДИНЕНИЕ Загрузка КАК Загрузка
        ПО (Загрузка.От <= ВсеИнтервалы.От)
            И ВсеИнтервалы.До <= Загрузка.До

Принцип решения в том, чтобы все моменты времени (все начала, концы интервалов, 0, 24) собрать без повторений в одну таблицу, затем по этой таблице построить все самые мелкие интервалы, а к ним уже присоединять включающие их интервалы работ, рабочего времени и тому подобное. Такой принцип будет работать и для больше чем двух таблиц пересекающихся интервалов. 

Проблема этого и всех приведенных запросов в том, что они будут сильно терять производительность при росте количества интервалов (если их станет больше нескольких тысяч). 
С этим можно справится, применяя прием из статьи http://catalog.mista.ru/public/402534/ для определения интервалов и прием из статьи http://catalog.mista.ru/public/551583/ (или его упрощенную версию) для определения пересечения интервалов.

55. Найти количество повторяющихся подряд по дням записей

Получить запросом кол-во повторяющихся ПОДРЯД записей

Например, имеются данные из двух полей "Дата" и "Явка": 1/ДА, 2/ДА, 3/ДА, 4/НЕТ, 5/НЕТ, 6/ДА, 7/НЕТ. Нужно получить таблицу из кол-ва повторяющихся подряд "Дата", "Явка", "РазПодряд".

Решение:

ВЫБРАТЬ
    Дано.Дата,
    МИНИМУМ(Дано.Явка) КАК Явка,
    РАЗНОСТЬДАТ(ЕСТЬNULL(МАКСИМУМ(ВЫБОР
                    КОГДА Раньше.Явка <> Дано.Явка
                        ТОГДА Раньше.Дата
                КОНЕЦ), ДОБАВИТЬКДАТЕ(МИНИМУМ(Раньше.Дата), ДЕНЬ, -1)), Дано.Дата, ДЕНЬ) КАК РазПодряд
ИЗ
    Дано КАК Дано
        ЛЕВОЕ СОЕДИНЕНИЕ Дано КАК Раньше
        ПО (Раньше.Дата <= Дано.Дата)

СГРУППИРОВАТЬ ПО
    Дано.Дата
УПОРЯДОЧИТЬ ПО
    Дано.Дата

54. Сравнение набора товаров, проданных сменами

Язык запросов

Если смена 1 и смена 2 продали одинаковые товары, то между ними в итоговой таблице должен стоять знак "=", иначе "<>"

Решение:

ВЫБРАТЬ РАЗЛИЧНЫЕ
    Дано.Смена,
    ВЗ.Знак
ИЗ
    Дано КАК Дано,
    (ВЫБРАТЬ
        МИНИМУМ(ВЫБОР
                КОГДА Дано1.Смена ЕСТЬ NULL 
                        ИЛИ Дано2.Смена ЕСТЬ NULL 
                    ТОГДА "<>"
                ИНАЧЕ "="
            КОНЕЦ) КАК Знак
    ИЗ
        Дано КАК Дано1
            ПОЛНОЕ СОЕДИНЕНИЕ Дано КАК Дано2
            ПО Дано1.Товар = Дано2.Товар
                И Дано1.Смена <> Дано2.Смена) КАК ВЗ

53. Найти документ, состав табличной части которого соответствует параметру - таблице значений

Запросом найти ТЧ документа по ТЗ в качестве параметра

ВЫБРАТЬ
    Товары.Номенклатура,
    Товары.Количество
ПОМЕСТИТЬ Эталон
ИЗ
    &Товары КАК Товары
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
    Товары.Ссылка,
    Товары.Номенклатура КАК Номенклатура,
    Товары.Количество КАК Количество
ПОМЕСТИТЬ ВсеСтроки
ИЗ
    Документ.ЗаказПокупателя.Товары КАК Товары

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ РАЗЛИЧНЫЕ
    ЗаказПокупателя.Ссылка,
    Эталон.Номенклатура,
    Эталон.Количество
ИЗ
    Эталон КАК Эталон,
    Документ.ЗаказПокупателя КАК ЗаказПокупателя
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Пары.Ссылка
ИЗ
    (ВЫБРАТЬ
        Пары.Ссылка КАК Ссылка,
        Пары.Номенклатура КАК Номенклатура,
        Пары.Количество КАК Количество,
        КОЛИЧЕСТВО(*) КАК Признак
    ИЗ
        ВсеСтроки КАК Пары
    
    СГРУППИРОВАТЬ ПО
        Пары.Ссылка,
        Пары.Номенклатура,
        Пары.Количество) КАК Пары

СГРУППИРОВАТЬ ПО
    Пары.Ссылка

ИМЕЮЩИЕ
    МИНИМУМ(Пары.Признак) = 2

52. Распределение товаров по ячейкам в запросе

"Распределение в запросе" или "избавляемся от перебора"

ВЫБРАТЬ
    Ячейки.Ячейка,
    СУММА(Слева.Количество) - МИНИМУМ(Ячейки.Количество) КАК КоличествоОт,
    СУММА(Слева.Количество) КАК КоличествоДо
ПОМЕСТИТЬ ЛинейкаЯчеек
ИЗ
    Ячейки КАК Ячейки
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Ячейки КАК Слева
        ПО (Слева.Ячейка <= Ячейки.Ячейка)

СГРУППИРОВАТЬ ПО
    Ячейки.Ячейка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Товары.Товар,
    СУММА(Слева.Количество) - МИНИМУМ(Товары.Количество) КАК КоличествоОт,
    СУММА(Слева.Количество) КАК КоличествоДо
ПОМЕСТИТЬ ЛинейкаТоваров
ИЗ
    Товары КАК Товары
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Товары КАК Слева
        ПО (Слева.Товар <= Товары.Товар)

СГРУППИРОВАТЬ ПО
    Товары.Товар
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Ячейки.Ячейка КАК Ячейка,
    Товары.Товар КАК Товар,
    ВЫБОР
        КОГДА Товары.КоличествоДо < Ячейки.КоличествоДо
            ТОГДА Товары.КоличествоДо
        ИНАЧЕ Ячейки.КоличествоДо
    КОНЕЦ - ВЫБОР
        КОГДА Товары.КоличествоОт > Ячейки.КоличествоОт
            ТОГДА Товары.КоличествоОт
        ИНАЧЕ Ячейки.КоличествоОт
    КОНЕЦ КАК Количество
ИЗ
    ЛинейкаЯчеек КАК Ячейки
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЛинейкаТоваров КАК Товары
        ПО Ячейки.КоличествоОт < Товары.КоличествоДо
            И Ячейки.КоличествоДо > Товары.КоличествоОт

Идея запроса в том, чтобы построить друг против друга линейку товаров и ячеек и найти пересечение отрезков на этих линейках. Вот в этом обсуждении есть соответствующая картинка: http://forum.infostart.ru/forum9/topic32459/message361861/#message361861 .

51. Объединение пересекающихся периодов в запросе

Требуется объединить перекрывающиеся периоды.

Например, шесть периодов

01.01.16 - 10.03.16;  01.02.16 - 20.03.16; 30.03.16 - 15.04.16; 10.04.16 - 12.04.16; 11.04.16 - 25.04.16; 30.04-16 - 10.05.16

должны объединиться в три

01.01.16 - 20.03.16; 30.03.16 - 25.04.16; 30.04-16 - 10.05.16

Вот самое простое решение:

ВЫБРАТЬ РАЗЛИЧНЫЕ
    Край.От
ПОМЕСТИТЬ ЛевыеКрая
ИЗ
    Интервалы КАК Край
        ЛЕВОЕ СОЕДИНЕНИЕ Интервалы КАК Интервалы
        ПО (Интервалы.От < Край.От)
            И Край.От <= Интервалы.До
ГДЕ
    Интервалы.От ЕСТЬ NULL 
;

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

ВЫБРАТЬ РАЗЛИЧНЫЕ
    Край.До
ПОМЕСТИТЬ ПравыеКрая
ИЗ
    Интервалы КАК Край
        ЛЕВОЕ СОЕДИНЕНИЕ Интервалы КАК Интервалы
        ПО (Интервалы.От <= Край.До)
            И Край.До < Интервалы.До
ГДЕ
    Интервалы.От ЕСТЬ NULL 
;

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

ВЫБРАТЬ
    ЛевыеКрая.От,
    МИНИМУМ(ПравыеКрая.До) КАК До
ИЗ
    ЛевыеКрая КАК ЛевыеКрая
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПравыеКрая КАК ПравыеКрая
        ПО ЛевыеКрая.От <= ПравыеКрая.До

СГРУППИРОВАТЬ ПО
    ЛевыеКрая.От

50. Выделение разрядов числа без использования округления и деления по модулю

Функция на размышление

Первый параметр функции - число из максимум пяти разрядов цифр "0" и "1", второй параметр - номер разряда.

Функция, возвращающая значение разряда:

Функция Ф(Х, У)
    Возврат ?(У < 2, 0 + (Х > 9999), Ф((Х - 10000 * (Х > 9999)) * 10, У - 1))
КонецФункции

49. Посчитать запросом суммарную длительность различных состояний

Подсчитать время в работе и время в ремонте

Запрос без изысков:

ВЫБРАТЬ
    &Дата1 КАК Период,
    НаНачало.Скважина,
    НаНачало.Состояние
ПОМЕСТИТЬ Дано
ИЗ
    РегистрСведений.Резерв.СрезПоследних(&Дата1, ) КАК НаНачало

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Резерв.Период,
    Резерв.Скважина,
    Резерв.Состояние
ИЗ
    РегистрСведений.Резерв КАК Резерв
ГДЕ
    Резерв.Период МЕЖДУ &Дата1 И &Дата2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    &Дата2,
    НаКонец.Скважина,
    НаКонец.Состояние
ИЗ
    РегистрСведений.Резерв.СрезПоследних(&Дата2, ) КАК НаКонец
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Раньше.Период,
    Раньше.Скважина,
    Раньше.Состояние,
    РАЗНОСТЬДАТ(Раньше.Период, МИНИМУМ(Позже.Период), СЕКУНДА) КАК Длительность
ПОМЕСТИТЬ Интервалы
ИЗ
    Дано КАК Раньше
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Дано КАК Позже
        ПО Раньше.Скважина = Позже.Скважина
            И Раньше.Период < Позже.Период

СГРУППИРОВАТЬ ПО
    Раньше.Период,
    Раньше.Скважина,
    Раньше.Состояние
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Интервалы.Скважина,
    Интервалы.Состояние,
    СУММА(Интервалы.Длительность) КАК Длительность
ИЗ
    Интервалы КАК Интервалы

СГРУППИРОВАТЬ ПО
    Интервалы.Скважина,
    Интервалы.Состояние

48. Разбиение произвольного периода на интервалы в запросе

[v8] Разбиение произвольного периода на интервалы (в запросе)

ВЫБРАТЬ
    0 КАК Х
ПОМЕСТИТЬ Бит
ОБЪЕДИНИТЬ
ВЫБРАТЬ
    1
;
ВЫБРАТЬ
    Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) КАК Х
ПОМЕСТИТЬ Периоды
ИЗ
    Бит КАК Б0,
    Бит КАК Б1,
    Бит КАК Б2,
    Бит КАК Б3,
    Бит КАК Б4,
    Бит КАК Б5
ГДЕ
    Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * Б5.Х)))) < РАЗНОСТЬДАТ(&Дата1, &Дата2, МЕСЯЦ)
;
ВЫБРАТЬ
    ЕСТЬNULL(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Начала.Х + 1), МЕСЯЦ), &Дата1) КАК ДатаНачала,
    ЕСТЬNULL(КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&Дата1, МЕСЯЦ, Окончания.Х), МЕСЯЦ), &Дата2) КАК ДатаОкончания
ИЗ
    Периоды КАК Начала
        ПОЛНОЕ СОЕДИНЕНИЕ Периоды КАК Окончания
        ПО (Начала.Х + 1 = Окончания.Х)

Важно: этот вариант не отрабатывает ситуацию отсутствия необходимости разбивки: если Дата1 и Дата2 находятся в одном месяце!

47. Поиск свободного штрихкода (EAN-13) внутри одного префикса

Поиск свободного штрихкода (EAN-13) внутри одного префикса

Решение основано на непосредственном получении следующего кода. Без необходимости перевода в числовой тип. 
В штрих-коде ищется последняя серия девяток. Она заменяется на серию нулей. Предшествующая цифра заменяется следующей в ряду цифр. Начало сохраняется. То есть решается задача инкрементирования числа непосредственно в символьном виде:

ВЫБРАТЬ 0 КАК Х ПОМЕСТИТЬ Р1 ОБЪЕДИНИТЬ ВЫБРАТЬ 1
;
ВЫБРАТЬ А.Х + 2 * Б.Х КАК Х ПОМЕСТИТЬ Р2 ИЗ Р1 КАК А, Р1 КАК Б
;
ВЫБРАТЬ А.Х + 4 * Б.Х КАК Х ПОМЕСТИТЬ Р4 ИЗ Р2 КАК А, Р2 КАК Б
;
ВЫБРАТЬ ВЫРАЗИТЬ(ПОДСТРОКА(ШтрихКод, 1, А.Х - 1) КАК СТРОКА12) 
+ ПОДСТРОКА("123456789", Б.Х + 1, 1) 
+ ПОДСТРОКА("000000000000", А.Х + 1, 12) КАК ШтрихКод
ПОМЕСТИТЬ ДаноПлюс 
ИЗ РегистрСведений_ШтрихкодыНоменклатуры, Р4 КАК А, Р4 КАК Б
ГДЕ ШтрихКод ПОДОБНО ПОДСТРОКА("%999999999999", 1, 13 - А.Х) 
И ШтрихКод НЕ ПОДОБНО ПОДСТРОКА("%999999999999", 1, 14 - А.Х)
И Б.Х < 9 И ПОДСТРОКА(ШтрихКод, А.Х, 1) = ПОДСТРОКА("012345678", Б.Х + 1, 1)
;
ВЫБРАТЬ ШтрихКод
ИЗ ДаноПлюс
ГДЕ ШтрихКод НЕ В 
(ВЫБРАТЬ Дано.ШтрихКод ИЗ РегистрСведений_ШтрихкодыНоменклатуры КАК Дано)

Из-за глюка движка форума ВЫРАЗИТЬ _ КАК СТРОКА12 пришлось написать без скобок вокруг 12.

46. Выбор записи по номеру из НЕПРОНУМЕРОВАННОЙ таблицы

Расчёт медианы числовых рядов запросом

ВЫБРАТЬ
    0 КАК Х
ПОМЕСТИТЬ Бит

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    1
;
ВЫБРАТЬ
    NULL КАК Х
ПОМЕСТИТЬ Сдвиг
ИЗ
    Бит КАК Б0,
    Бит КАК Б1,
    Бит КАК Б2,
    Бит КАК Б3,
    Бит КАК Б4,
    Бит КАК Б5,
    Бит КАК Б6,
    Бит КАК Б7
ГДЕ
    Б0.Х + 2 * (Б1.Х + 2 * (Б2.Х + 2 * (Б3.Х + 2 * (Б4.Х + 2 * (Б5.Х + 2 * (Б6.Х + 2 * Б7.Х)))))) < 256 - &Номер
;
ВЫБРАТЬ
    Дано.Х КАК Х
ПОМЕСТИТЬ Дано
ИЗ 
&Дано КАК Дано
;
ВЫБРАТЬ ПЕРВЫЕ 2
    ВЗ.Х
ИЗ
    (ВЫБРАТЬ ПЕРВЫЕ 256
        ВЗ.Х
    ИЗ
        (ВЫБРАТЬ
            Сдвиг.Х
        ИЗ
            Сдвиг КАК Сдвиг
        
        ОБЪЕДИНИТЬ ВСЕ
        
        ВЫБРАТЬ
            Дано.Х
        ИЗ
            Дано КАК Дано) КАК ВЗ
    
    УПОРЯДОЧИТЬ ПО
        Х) КАК ВЗ

УПОРЯДОЧИТЬ ПО
    Х УБЫВ

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

45. Как в запросе секунды преобразовать в часы и минуты

ссылка

РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, &ДлительностьВСекундах), ЧАС) 
    + МИНУТА(ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 1, 1), СЕКУНДА, &ДлительностьВСекундах)) / 100

44. Убрать префикс и лидирующие нули из номера

Простой способ убрать префикс и лидирующие нули из номера

Первый вариант:

Функция ЧислоСправа(Стр, К = 0)
   Возврат ?(Цел(КодСимвола(Прав("!" + Стр, К + 1)) / 5 - 10.5), Формат(Число("0" + Прав(Стр, К)), "ЧГ="), ЧислоСправа(Стр, К + 1))
КонецФункции

Второй вариант:

Функция ЧислоСправа1(Номер)
   Возврат Формат(Число("0" + Сред(Номер, СтрДлина(СокрП(
   СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Номер
   , "0", " "), "1", " "), "2", " "), "3", " "), "4", " "), "5", " "), "6", " "), "7", " "), "8", " "), "9", " "))) + 1)), "ЧГ=")
КонецФункции

С новыми функциями СтрРазделить и СтрСоединить есть еще более простой вариант.

43. Перебор всех строковых комбинаций "0" и "1" в порядке возрастания числа единиц

http://forum.infostart.ru/forum9/topic147064/message1583278/#message1583278 

Очень полезная функция для организации перебора комбинаций. Без циклов!

Функция СледующийКод(Код)
    Возврат Прав(СтрЗаменить(Код, "1", "0") + Лев("1" + Код, Найти(Код, "0")) 
    + ?(Найти(Код, "01"), "0", "") + Сред(Код, Найти(Код + "01", "01") + 2), СтрДлина(Код))
КонецФункции

Например, для начального значения "00000" получается последовательность: 
"00000","00001","00010","00100","01000","10000","00011","00101", "01001","10001","00110","01010","10010","01100","10100","11000", "00111","01011","10011","01101","10101","11001","01110","10110", "11010","11100","0111","10111","11011","11101","11110","11111", "00000".

42. Транслитерация в запросе

На досуге [Как запросом по строке Танk001 найти Tanк001 в 1С]

Вот текст запроса, построенный на идее статьи Агрегатное суммирование строк в запросе – сложно, но не невозможно. В запросе производятся необходимые преобразования. То есть берется таблица Дано с кириллическими наименованиями, транслитируется по таблице ISO9 в наименования латинницей и соединяется с таблицей поиска. Определяется ключ связи (номер строки в таблице поиска). Расчет на строки длиной до 256.

ВЫБРАТЬ
    Дано.НомерСтроки,
    Дано.Наименование
ПОМЕСТИТЬ ДаноКириллица
ИЗ
    &ДаноКириллица КАК Дано
;
ВЫБРАТЬ
    "" "" КАК Буква,
    &СимволНПП КАК Замена
ПОМЕСТИТЬ ГОСТ79_2000

ОБЪЕДИНИТЬ ВЫБРАТЬ ""а"", ""a"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""б"", ""b"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""в"", ""v"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""г"", ""g"" 
ОБЪЕДИНИТЬ ВЫБРАТЬ ""д"", ""d"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""е"", ""e"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""ё"", ""yo""ОБЪЕДИНИТЬ ВЫБРАТЬ ""ж"", ""zh""
ОБЪЕДИНИТЬ ВЫБРАТЬ ""з"", ""z"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""и"", ""i"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""й"", ""j"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""к"", ""k""
ОБЪЕДИНИТЬ ВЫБРАТЬ ""л"", ""l"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""м"", ""m"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""н"", ""n"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""о"", ""o""
ОБЪЕДИНИТЬ ВЫБРАТЬ ""п"", ""p"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""р"", ""r"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""с"", ""s"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""т"", ""t"" 
ОБЪЕДИНИТЬ ВЫБРАТЬ ""у"", ""u"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""ф"", ""f"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""х"", ""x"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""ц"", ""cz""
ОБЪЕДИНИТЬ ВЫБРАТЬ ""ч"", ""ch""ОБЪЕДИНИТЬ ВЫБРАТЬ    ""ш"", ""sh""ОБЪЕДИНИТЬ ВЫБРАТЬ ""щ"",""shh""ОБЪЕДИНИТЬ ВЫБРАТЬ ""ъ"", """"
ОБЪЕДИНИТЬ ВЫБРАТЬ ""ы"",""y""  ОБЪЕДИНИТЬ ВЫБРАТЬ    ""ь"", """"  ОБЪЕДИНИТЬ ВЫБРАТЬ ""э"", ""e"" ОБЪЕДИНИТЬ ВЫБРАТЬ ""ю"", ""yu""
ОБЪЕДИНИТЬ ВЫБРАТЬ ""я"",""ya""

ИНДЕКСИРОВАТЬ ПО
    Буква
;
ВЫБРАТЬ
    0 КАК Х
ПОМЕСТИТЬ ЦИФРЫ

ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5
ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9
;
ВЫБРАТЬ
    А.Х * 10 + Б.Х + 1 КАК Х
ПОМЕСТИТЬ Числа
ИЗ
    ЦИФРЫ КАК А,
    ЦИФРЫ КАК Б
;
ВЫБРАТЬ
    Дано.НомерСтроки КАК ж,
    Числа.Х КАК ё,
    ЕСТЬNULL(ГОСТ.Замена, ПОДСТРОКА(Дано.Наименование, Числа.Х, 1)) КАК а
ПОМЕСТИТЬ Таб
ИЗ
    ДаноКириллица КАК Дано
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Числа КАК Числа
        ПО (ПОДСТРОКА(Дано.Наименование, Числа.Х, 1) + ""!"" <> ""!"")
        ЛЕВОЕ СОЕДИНЕНИЕ ГОСТ79_2000 КАК ГОСТ
        ПО (ПОДСТРОКА(Дано.Наименование, Числа.Х, 1) = ГОСТ.Буква)
;
ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ ж, ВЫРАЗИТЬ(ё / 2 КАК ЧИСЛО(15, 0)) е, ё, а ПОМЕСТИТЬ Шаг ИЗ Таб КАК Таб; УНИЧТОЖИТЬ Таб;
ВЫБРАТЬ ж, е ё, МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА а ИНАЧЕ """" КОНЕЦ) + МАКСИМУМ(ВЫБОР е * 2 - ё КОГДА 1 ТОГДА """"ИНАЧЕ Шаг.а КОНЕЦ) а
ПОМЕСТИТЬ Таб ИЗ Шаг СГРУППИРОВАТЬ ПО ж, е; УНИЧТОЖИТЬ Шаг;

ВЫБРАТЬ
    Дано.НомерСтроки,
    Дано.Наименование КАК Наименование
ПОМЕСТИТЬ ДаноЛатинница
ИЗ
    &ДаноЛатинница КАК Дано

ИНДЕКСИРОВАТЬ ПО
    Наименование
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Таб.ж КАК НомерСтроки,
   ДаноКириллица.Наименование КАК Кириллица,
    Таб.а КАК Латинница,
   ДаноЛатинница.НомерСтроки КАК КлючСвязи
ИЗ
    Таб КАК Таб 
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ДаноКириллица КАК ДаноКириллица 
        ПО Таб.ж = ДаноКириллица.НомерСтроки
        ЛЕВОЕ СОЕДИНЕНИЕ ДаноЛатинница КАК ДаноЛатинница 
        ПО Таб.а = ДаноЛатинница.Наименование

УПОРЯДОЧИТЬ ПО
    Таб.ж

41. Заполнение пропусков в таблице цветов

Помогите пожалуйста составить запрос

Есть таблица: 1 красный; 2 null; 3 null; 4 синий; 5 null; 6 белый; 7 null; 8 null

Нужно получить таблицу: 1 красный; 2 красный; 3 красный; 4 синий; 5 синий; 6 белый; 7 белый; 8 белый

Решение:

ВЫБРАТЬ
    Дано.Номер,
    ЕСТЬNULL(Выше.Цвет, Дано.Цвет)
ИЗ
    Дано КАК Дано
        ЛЕВОЕ СОЕДИНЕНИЕ Дано КАК Выше
        ПО (Дано.Цвет ЕСТЬ NULL )
            И (Выше.Номер В
                (ВЫБРАТЬ
                    МАКСИМУМ(Было.Номер) КАК Номер
                ИЗ
                    Дано КАК Было
                ГДЕ
                    Было.Номер < Дано.Номер
                    И НЕ Было.Цвет ЕСТЬ NULL ))

40. Количество дней недели (понедельников/вторников/...) в заданном диапазоне запросом

Количество дней недели (понедельников/вторников/...) в заданном диапазоне одним запросом

ВЫБРАТЬ
   Дни.ДеньНедели,
   РАЗНОСТЬДАТ(НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, -Дни.ДеньНедели), НЕДЕЛЯ)
, НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&КонецПериода, ДЕНЬ, 1 - Дни.ДеньНедели), НЕДЕЛЯ), ДЕНЬ) / 7 КАК КоличествоДней
ИЗ
   (ВЫБРАТЬ 1 КАК ДеньНедели ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5
   ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7) КАК Дни

39. Свернуть строки в таблице значений конкатенацией

ссылка

Дано.Сортировать("Поле1, Поле2");
ё = Дано.Количество();
Пока ё > 1 Цикл
   ё = ё - 1;
    Если Дано[ё - 1].Поле1 = Дано[ё].Поле1 И Дано[ё - 1].Поле2 = Дано[ё].Поле2 Тогда
        Дано[ё - 1].Поле3 = Дано[ё - 1].Поле3 + Дано[ё].Поле3;
        Дано.Удалить(ё)
    КонецЕсли 
КонецЦикла;

 

Примеры кода рефакторинг

См. также

Метод Дугласа-Пойкера для эффективного хранения метрик

Математика и алгоритмы Платформа 1C v8.2 Конфигурации 1cv8 Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    1714    stopa85    12    

33

Алгоритм симплекс-метода для решения задачи раскроя

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    4313    user1959478    50    

34

Регулярные выражения на 1С

Математика и алгоритмы Инструментарий разработчика Платформа 1С v8.3 Мобильная платформа Россия Абонемент ($m)

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

1 стартмани

09.06.2023    7343    4    SpaceOfMyHead    17    

56

Модель распределения суммы по базе

Математика и алгоритмы Платформа 1С v8.3 Россия Абонемент ($m)

Обычно под распределением понимают определение сумм пропорционально коэффициентам. Предлагаю включить сюда также распределение по порядку (FIFO, LIFO) и повысить уровень размерности до 2-х. 1-ое означает, что распределение может быть не только пропорциональным, но и по порядку, а 2-ое - это вариант реализации матричного распределения: по строкам и столбцам. Возможно вас заинтересует также необычное решение этой задачи через создание DSL на базе реализации текучего интерфейса

1 стартмани

21.03.2022    7817    7    kalyaka    11    

44

Изменения формата файлов конфигурации (CF) в 8.3.16

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Дополнение по формату файлов конфигурации (*.cf) в версии 8.3.16.

16.12.2021    4414    fishca    13    

36

Интересная задача на Yandex cup 2021

Математика и алгоритмы Бесплатно (free)

Мое решение задачи на Yandex cup 2021 (frontend). Лабиринт. JavaScript.

12.10.2021    8793    John_d    73    

46

Механизм анализа данных. Кластеризация.

Математика и алгоритмы Анализ учета Платформа 1С v8.3 Анализ и прогнозирование Бесплатно (free)

Подробный разбор, с примером использования, встроенного механизма кластеризации 1С.

31.08.2021    7710    dusha0020    8    

70
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. a_a_burlakov 284 20.02.18 09:16 Сейчас в теме
Магия.
mvxyz; mark_oilbass; FuNNyHoRRoR; par_62; Liris; nofear; корум; bulpi; Alien_job; ipoloskov; rintik; Ibrogim; wbazil; akR00b; CyberCerber; +15 Ответить
2. DarkUser 20.02.18 11:30 Сейчас в теме
3. headMade 144 20.02.18 11:47 Сейчас в теме
Подскажите что можно взять за основу для определения интервалов чисел.
Например есть массив: 1,2,3,6,7,8,11,12,15.
Надо получить интервалы 1-3,6-8,11-12,15-15.

Спасибо.
4. ildarovich 7844 20.02.18 13:13 Сейчас в теме
5. headMade 144 20.02.18 13:38 Сейчас в теме
(4) а с использованием запроса?
6. ildarovich 7844 20.02.18 13:43 Сейчас в теме
(5) Тогда там же, но задача 14. В задаче речь идет о датах, но будет работать и на числах
7. 🅵🅾️🆇 522 20.02.18 14:44 Сейчас в теме
(0)
Определение суммарного покрытия перекрывающихся интервалов

Еще раз спасибо за это решение, очень выручила подсказка.

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

8. klinval 337 20.02.18 16:18 Сейчас в теме
65.
Есть массив А из элементов некоторого справочника и есть справочник Б с табличной частью из элементов того же справочника. Найти элемент Б, где список точно совпадает с массивом А (ни больше ни меньше).

ВЫБРАТЬ
    Менеджеры.Ссылка
ИЗ
    Справочник.Контрагенты.МенеджерыПокупателя КАК Менеджеры
ГДЕ
    Менеджеры.МенеджерПокупателя В(&Массив)
СГРУППИРОВАТЬ ПО
    Менеджеры.Ссылка
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Менеджеры.МенеджерПокупателя) = &МассивКоличество
Показать

Не работает если учитывать условие "ни больше ни меньше". Когда больше - запрос отрабатывает неверно.
Проверяю на БП 3.0 на запросе:
ВЫБРАТЬ
	КонтрагентыИсторияКПП.Ссылка КАК Ссылка
ИЗ
	Справочник.Контрагенты.ИсторияКПП КАК КонтрагентыИсторияКПП
ГДЕ
	КонтрагентыИсторияКПП.КПП В(&МассивКПП)

СГРУППИРОВАТЬ ПО
	КонтрагентыИсторияКПП.Ссылка

ИМЕЮЩИЕ
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КонтрагентыИсторияКПП.КПП) = &МассивКППКоличество
Показать

Допустим возьмём контрагента у которого КПП 3 строки: 775003035, 773601001 и 631050001
В запрос передадим массив КПП: 775003035; 773601001 и МассивКППКоличество = 2;
Запрос возвращает результат - этого контрагента, хотя у него 3 сроки!
Рабочий запрос:
ВЫБРАТЬ РАЗЛИЧНЫЕ
	КонтрагентыИсторияКПП.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВсеКонтрагентыСЭтимиДанными
ИЗ
	Справочник.Контрагенты.ИсторияКПП КАК КонтрагентыИсторияКПП
ГДЕ
	КонтрагентыИсторияКПП.КПП В(&МассивКПП)

СГРУППИРОВАТЬ ПО
	КонтрагентыИсторияКПП.Ссылка

ИМЕЮЩИЕ
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КонтрагентыИсторияКПП.КПП) = &МассивКППКоличество
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
	КонтрагентыИсторияКПП.Ссылка КАК Ссылка
ИЗ
	ВсеКонтрагентыСЭтимиДанными КАК ВсеКонтрагентыСЭтимиДанными
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты.ИсторияКПП КАК КонтрагентыИсторияКПП
		ПО ВсеКонтрагентыСЭтимиДанными.Ссылка = КонтрагентыИсторияКПП.Ссылка

СГРУППИРОВАТЬ ПО
	КонтрагентыИсторияКПП.Ссылка

ИМЕЮЩИЕ
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КонтрагентыИсторияКПП.КПП) = &МассивКППКоличество
Показать
9. ildarovich 7844 20.02.18 16:57 Сейчас в теме
(8) Вы правы, проблему увидел, в ближайшее время исправлю.
11. ildarovich 7844 21.02.18 10:29 Сейчас в теме
(8) Все же решил исправить по-своему. Для старых версий платформы так:
ВЫБРАТЬ
	КонтрагентыИсторияКПП.Ссылка КАК Ссылка
ИЗ
	Справочник.Контрагенты.ИсторияКПП КАК КонтрагентыИсторияКПП
СГРУППИРОВАТЬ ПО
	КонтрагентыИсторияКПП.Ссылка
ИМЕЮЩИЕ
	СУММА(ВЫБОР
			КОГДА КонтрагентыИсторияКПП.КПП В (&МассивКПП)
				ТОГДА 1
			ИНАЧЕ 0.000001
		КОНЕЦ) = &МассивКППКоличество
Показать
Для новых, где логическое выражение можно записывать сразу в поле запроса, так:
ВЫБРАТЬ
	КонтрагентыИсторияКПП.Ссылка КАК Ссылка
ИЗ
	Справочник.Контрагенты.ИсторияКПП КАК КонтрагентыИсторияКПП
СГРУППИРОВАТЬ ПО
	КонтрагентыИсторияКПП.Ссылка
ИМЕЮЩИЕ
	КОЛИЧЕСТВО(*) = &МассивКППКоличество И
	МИНИМУМ(КонтрагентыИсторияКПП.КПП В (&МассивКПП)) = ИСТИНА
Показать
В числе строчек даже получился выигрыш.
Спасибо за внимательность!
KoC_one; Liris; корум; klinval; +4 Ответить
10. BackinSoda 21.02.18 08:40 Сейчас в теме
12. Дмитрий74Чел 234 21.02.18 16:38 Сейчас в теме
Оглавление

72. Очистка строки от нецифровых символов
71. Определение суммарного покрытия перекрывающихся интервалов
70. Определение пересечения интервалов в кольце
69. Быстрое удаление строк в таблице значений
68. Получение интервалов неизменности курсов валют
67. Определение пропусков в последовательности чисел
66. Инвертирование периодов в запросе
65. Проверка совпадения таблиц
64. Проверка совпадения таблиц путем сравнения полного и внутреннего соединения
63. Получение списка простых чисел в запросе
62. Определение периодов работы сотрудников по данным СКУД
61. Найти документы, во всех строках которых колонка количество меньше либо равна нулю
60. Определение плановых остатков товара с учетом предшествующих фактических и будущих плановых продаж
59. Сравнение плановых и фактических дней отпуска
58. Получить дату по номеру дня недели и его порядковому номеру в месяце
57. Получение предпоследнего курса валюты
56. Определить элементарные интервалы, образующиеся при пересечении всех исходных интервалов
55. Найти количество записей, повторяющихся подряд несколько дней
54. Сравнение набора товаров, проданных сменами
53. Найти документ, состав табличной части которого соответствует параметру - таблице значений
52. Распределение товаров по ячейкам в запросе
51. Объединение пересекающихся периодов в запросе
50. Выделение разрядов числа без использования округления и деления по модулю
49. Посчитать запросом суммарную длительность различных состояний
48. Разбиение произвольного периода на интервалы в запросе
47. Поиск свободного штрихкода внутри одного префикса
46. Выбор записи по номеру из НЕПРОНУМЕРОВАННОЙ таблицы
45. Как в запросе секунды преобразовать в часы и минуты
44. Убрать префикс и лидирующие нули из номера
43. Перебор всех строковых комбинаций "0" и "1" в порядке возрастания числа единиц ("00000"->"00001"->"00010"-> ..."01011"...)
42. Транслитерация в запросе
41. Заполнение пропусков в таблице цветов
40. Количество дней недели (понедельников/вторников/...) в заданном диапазоне запросом
39. Свернуть строки в таблице значений конкатенацией
ДмитрийС; +1 Ответить
13. ildarovich 7844 21.02.18 16:43 Сейчас в теме
(12) Спасибо, сделаю это оглавление в самой статье.
14. fixxxer834 26.02.18 16:38 Сейчас в теме
67. следующий вариант работает на порядки быстрее для больших таблиц (если не ПЕРВЫЕ 1 - выбирает все пропущенные значения и следующее по порядку):
ВЫБРАТЬ ПЕРВЫЕ 1
Т1.Х + 1
ИЗ
Дано Т1
ЛЕВОЕ СОЕДИНЕНИЕ
Дано Т2
ПО
Т2.Х = Т1.Х + 1
ГДЕ
Т2.Х Есть Null
УПОРЯДОЧИТЬ ПО
Т1.Х

З.Ы. на таблице в 1 млн. записей с индексированием по полю X (иначе какой смысл искать "дырки" в большой таблице и оставлять это поле неиндексированным) данный запрос выполняется за доли секунды в том случае как предложенный - десяток секунд.
15. ildarovich 7844 26.02.18 16:58 Сейчас в теме
(14)
иначе какой смысл искать "дырки" в большой таблице и оставлять это поле неиндексированным
все же бывают случаи и неиндексированных таблиц (например, если это временная таблица) и файловых баз и других СУБД, поэтому знать и уметь сравнивать разные варианты, кроме очевидных, бывает нужно.
16. meganibler 74 06.04.18 11:08 Сейчас в теме
может кому пригодится: нормализация представления числа

// Приводит переданные числовые значения Мантиссы и Порядка к нормализованной форме
//	Нормализованной формой числа с плавающей запятой считается форма, когда Мантисса находится в интервале 1 ⩽ М < 10
//
// Параметры:
//  ЗначениеМантисса		 - Число - значение числа без учёта порядка
//  ЗначениеПорядок			 - Число - степень основания числа, на которое умножается мантисса
//  НормализованнаяМантисса	 - Число - возвращаемое нормализованное значение мантиссы
//  НормализованныйПорядок	 - Число - возвращаемое нормализованное значение порядка
//
Процедура НормализоватьЗначениеЧисла(ЗначениеМантисса, ЗначениеПорядок = 0, НормализованнаяМантисса = 0, НормализованныйПорядок = 0) Экспорт
	
	Если ЗначениеМантисса = 0 Тогда 
		Возврат;	
	КонецЕсли;
	Порядок = Log10(?(ЗначениеМантисса < 0, - ЗначениеМантисса, ЗначениеМантисса)); 
	Если Порядок > 0 Тогда 
		Порядок = Цел(Порядок);
	Иначе
		Если Не Порядок = Цел(Порядок) Тогда 
			Порядок = Цел(Порядок) - 1;
		КонецЕсли;	
	КонецЕсли;
	НормализованныйПорядок = Порядок + ЗначениеПорядок;
	НормализованнаяМантисса = ЗначениеМантисса * Pow(10, ЗначениеПорядок - НормализованныйПорядок);
	
КонецПроцедуры
Показать


Пример1: ЗначениеМантисса = 0,1; ЗначениеПорядок = 0; НормализованнаяМантисса = 1; НормализованныйПорядок = -1 (0,1)->(1·10^-1)
Пример2: ЗначениеМантисса = 10; ЗначениеПорядок = 6; НормализованнаяМантисса = 1; НормализованныйПорядок = 7; (10·10^6)->(1·10^7)
Пример3: ЗначениеМантисса = 500; ЗначениеПорядок = 0; НормализованнаяМантисса = 5; НормализованныйПорядок = 2; (500)->(5·10^2)
17. bolshoi 06.04.18 14:41 Сейчас в теме
Тоже поделюсь.

1. Количество знаков после запятой (максимум 27).

Точность = СтрДлина(Сред("" + Макс(-Значение, Значение) % 1, 3));


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

ЕстьЗаполненныеЗначения = (Таблица.НайтиСтроки(Новый Структура("ИмяКолонки", ПустоеЗначение)).Количество() <> Таблица.Количество());
18. Marik 76 10.04.18 07:23 Сейчас в теме
По поводу "Быстрое удаление строк в таблице значений" есть сомнение в приведенном способе.

1. Если таблица значений занимает более 100-ни Мб в ОЗУ, то получаем лишний расход ОЗУ (на 1-ю и 2-ю таблицу)
2. Если в значениях таблицы значений есть ссылочные данные, то получаем нагрузку на процессор

Вариант синтаксиса: Скопировать по отбору
Описание:
Создает копию таблицы значений.
Если указан отбор, то только строки из отбора будут скопированы. Если отбор не указан, то будут скопированы все строки таблицы значений. Если указаны колонки, то только эти колонки будут скопированы. Иначе, будут скопированы все колонки таблицы значений


Наилучшим решением будет удаление по отбору по индексированной колонке
РабочаяТаблица.Индексы.Добавить("КУдалению");
найдСтр = РабочаяТаблица.НайтиСтроки(Новый Структура("КУдалению",Истина));
Для к=0 По найдСтр.ВГраница() Цикл
РабочаяТаблица.Удалить(найдСтр[к]);
КонецЦикла;
19. ildarovich 7844 10.04.18 13:14 Сейчас в теме
(18) Сомневаться нужно, но, чтобы сделать выводы, нужны замеры. "Лишнего" расхода ОЗУ, нагрузки на процессор (видимо, имеется ввиду работа со структурой для работы сборщика мусора). Просто сказать "наилучшим решением будет" в данном случае недостаточно. Выигрыш приема из (69) был настолько большим (в моих измерениях), что его указанные минусы не перекрывают. - Попробуйте сделать замеры сами!
20. Marik 76 10.04.18 19:44 Сейчас в теме
Пожалуйста вот замеры, обратите на 2-ю строку, отбрасывая все лишнее, только процесс удаления и создания:
1. Удаление не вашим способом


2. Удаление вашим способом


Почему так происходит? Понимание приходит, если кодить не только в 1С, а например кодить в ООП, в Java. На самом деле при вашем способе создается НОВЫЙ объект, в который копируются данные из СТАРОГО объекта, причем при наличии ссылочных типов, идет нагрузка на процессор (можно почитать про коллекции в Java, там ясно объясняется разница между insert/delete с примитивными типами и object). Я не могу тут привести размеры ОЗУ и нагрузку на процессор (придется заморочится), но поверьте я часто работаю с большими данными и вообще я считаю наиболее оптимальным способом является удаление через запрос.

Со всем уважением к вам! Ваши статьи лаконичны и самое главное практичны!
21. spacecraft 10.04.18 20:58 Сейчас в теме
(20) считаете вышеприведенные варианты равнозначными?
"РабочаяТаблица.Индексы.Добавить("КУдалению");" Это ничего не говорит?
А теперь провести тесты с этим кодов в обоих способах и без этого кода. Результаты изменились? Неожиданно?
22. Marik 76 11.04.18 18:43 Сейчас в теме
Я просто отметил, что быстрее будет удалить
Наилучшим решением будет удаление по отбору по индексированной колонке

А то что, без этой строки
РабочаяТаблица.Индексы.Добавить("КУдалению");

будет дольше, это и так понятно. С самого начала я отметил - удаление по отбору по индексированной колонке.
23. spacecraft 11.04.18 20:14 Сейчас в теме
(22)
будет дольше, это и так понятно. С самого начала я отметил - удаление по отбору по индексированной колонке.

А почему отказываете в индексации в другом примере? Где сказано, что в 69 обязательно не индексированная колонка?
С моей точки зрения там сказано, что при прочих равных условий будет быстрее создать новую таблицу, чем удалять строки.
Вы нашли "неравные" условия и сравниваете.
Рассматривая Ваше высказывание: "Наилучшим решением будет удаление по отбору по индексированной колонке", можно ответить:
"Быстрее всего удаляются строки путем копирования оставшихся строк по условию, обратному к условию удаления". При достаточно большой ТЗ, когда индексация начинает оказывать положительный результат, с индексацией нужной колонки
Но последнее предложение должно пониматься нормальным разработчиком по-умолчанию.
24. Marik 76 12.04.18 09:49 Сейчас в теме
(23)
Хорошо вот вам равные условия:
	РабочаяТаблица.Индексы.Добавить("КУдалению");
	РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению",Истина));
	//найдСтр = РабочаяТаблица.НайтиСтроки(Новый Структура("КУдалению",Истина));
	//Для к = 0 По найдСтр.ВГраница() Цикл
	//	РабочаяТаблица.Удалить(найдСтр[к]);
	//КонецЦикла;


результат


и соответственно
	РабочаяТаблица.Индексы.Добавить("КУдалению");
	//РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению",Истина));
	найдСтр = РабочаяТаблица.НайтиСтроки(Новый Структура("КУдалению",Истина));
	Для к = 0 По найдСтр.ВГраница() Цикл
		РабочаяТаблица.Удалить(найдСтр[к]);
	КонецЦикла;


результат
26. spacecraft 12.04.18 10:18 Сейчас в теме
(24) снова не то смотрите.
Код:
Процедура ОсновныеДействияФормыЗаполнитьТЗ(Кнопка)
	ТЗ.Колонки.Добавить("Номер", Новый ОписаниеТипов("Число"));
	ТЗ.Колонки.Добавить("КУдалению",Новый ОписаниеТипов("Булево"));
	Для к=1 По 300000 Цикл
		СтрТЗ =	ТЗ.Добавить();
		СтрТЗ.Номер = к;
		СтрТЗ.КУдалению = к%2 = 0;
	КонецЦикла;
	Сообщить(ТЗ.Количество());
КонецПроцедуры

Процедура ОсновныеДействияФормыАнализУдалениемСтрокТЗ(Кнопка)
	
	ТЗКопия = ТЗ.Скопировать();
	ТЗКопия.Индексы.Добавить("КУдалению");
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	найдСтр = ТЗКопия.НайтиСтроки(Новый Структура("КУдалению",Истина));
    Для к = 0 По найдСтр.ВГраница() Цикл
        ТЗКопия.Удалить(найдСтр[к]);
	КонецЦикла;
	ВремяЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяНачала;
	Сообщить("Кол-во элементов: "+ ТЗКопия.Количество());
	Сообщить("Время выполнения удалением: "+ ВремяЗамера);
КонецПроцедуры

Процедура ОсновныеДействияФормыАнализКопированиемТЗ(Кнопка)
	ТЗКопия = ТЗ.Скопировать();
	ТЗКопия.Индексы.Добавить("КУдалению");
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	ТЗКопия = ТЗКопия.Скопировать(Новый Структура("КУдалению",Истина));
	ВремяЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяНачала;
	Сообщить("Кол-во элементов: "+ ТЗКопия.Количество());
	Сообщить("Время выполнения копированием: "+ ВремяЗамера);
КонецПроцедуры
Показать

Замеры:
300 000
Кол-во элементов: 150 000
Время выполнения удалением: 2 014
Кол-во элементов: 150 000
Время выполнения копированием: 222
Кол-во элементов: 150 000
Время выполнения удалением: 2 000
Кол-во элементов: 150 000
Время выполнения копированием: 225
Кол-во элементов: 150 000
Время выполнения удалением: 1 973
Кол-во элементов: 150 000
Время выполнения копированием: 224
Кол-во элементов: 150 000
Время выполнения удалением: 2 025
Кол-во элементов: 150 000
Время выполнения копированием: 227
Кол-во элементов: 150 000
Время выполнения удалением: 1 989
Кол-во элементов: 150 000
Время выполнения копированием: 222

Что-то еще нужно доказывать?
27. Marik 76 13.04.18 08:10 Сейчас в теме
(26)
Ну что же, теперь понятно, почему у вас отличные результаты чем у меня
вот как выглядит мой тест

Процедура СформироватьРабочуюТаблицу()
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ *, ЛОЖЬ КАК КУдалению........";

	РабочаяТаблица = Запрос.Выполнить().Выгрузить();
	
	Счетчик = 1;
	Для каждого ТС из РабочаяТаблица Цикл
		Если Счетчик = 1 Тогда
			ТС.КУдалению = Истина;
			Счетчик = 0;
		Иначе
			Счетчик = 1;
		КонецЕсли;
	КонецЦикла;

	РабочаяТаблица.Индексы.Добавить("КУдалению");
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры

Процедура Кнопка1Нажатие(Элемент)
	СформироватьРабочуюТаблицу();
	найдСтр = РабочаяТаблица.НайтиСтроки(Новый Структура("КУдалению",Истина));
	Для к = 0 По найдСтр.ВГраница() Цикл
		РабочаяТаблица.Удалить(найдСтр[к]);
	КонецЦикла;
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры

Процедура Кнопка2Нажатие(Элемент)
	СформироватьРабочуюТаблицу();
	РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению",Истина));
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры
Показать


я подаю на вход ТЗ из запроса, вы - нет....поэтому результаты тестов у нас разные

Так что и я прав и вы правы.....
28. spacecraft 13.04.18 08:31 Сейчас в теме
(27)
я подаю на вход ТЗ из запроса, вы - нет....поэтому результаты тестов у нас разные

Это шутка такая? Не смешно.

Процедура Кнопка1Нажатие(Элемент)
    СформироватьРабочуюТаблицу();
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	найдСтр = РабочаяТаблица.НайтиСтроки(Новый Структура("КУдалению",Истина));
    Для к = 0 По найдСтр.ВГраница() Цикл
        РабочаяТаблица.Удалить(найдСтр[к]);
	КонецЦикла;
	ВремяЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяНачала;
    Сообщить(РабочаяТаблица.Количество());
	Сообщить("Время выполнения удалением: "+ ВремяЗамера);
КонецПроцедуры

Процедура Кнопка2Нажатие(Элемент)
    СформироватьРабочуюТаблицу();
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
    РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению",Истина));
	ВремяЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах()-ВремяНачала;
    Сообщить(РабочаяТаблица.Количество());
	Сообщить("Время выполнения копированием: "+ ВремяЗамера);
КонецПроцедуры
Показать

Что покажет этот код?
29. Marik 76 13.04.18 08:45 Сейчас в теме
(28)
Нет не шутка

Вариант 1 - ваше тз на вход через запрос

Процедура СформироватьРабочуюТаблицу()
	//тз = Новый ТаблицаЗначений;
	//тз.Колонки.Добавить("Номер", Новый ОписаниеТипов("Число"));
	//тз.Колонки.Добавить("КУдалению",Новый ОписаниеТипов("Булево"));
	//Для к=1 По 300000 Цикл
	//	СтрТЗ = тз.Добавить();
	//	СтрТЗ.Номер = к;
	//	СтрТЗ.КУдалению = к%2 = 0;
	//КонецЦикла;
	//
	//Запрос = Новый Запрос;
	//Запрос.УстановитьПараметр("ВнешнийИсточник", тз);
	//Запрос.Текст = 
	//"ВЫБРАТЬ
	//|	ВН.Номер КАК Номер,
	//|	ВН.КУдалению КАК КУдалению
	//|ПОМЕСТИТЬ втВрем
	//|ИЗ
	//|	&ВнешнийИсточник КАК ВН
	//|;
	//|
	//|////////////////////////////////////////////////////////////­////////////////////
	//|ВЫБРАТЬ
	//|	втВрем.Номер,
	//|	втВрем.КУдалению
	//|ИЗ
	//|	втВрем КАК втВрем";
	//РабочаяТаблица = Запрос.Выполнить().Выгрузить();
		
	РабочаяТаблица.Индексы.Добавить("КУдалению");
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры

Процедура Кнопка1Нажатие(Элемент)
	СформироватьРабочуюТаблицу();
	найдСтр = РабочаяТаблица.НайтиСтроки(Новый Структура("КУдалению",Истина));
	Для к = 0 По найдСтр.ВГраница() Цикл
		РабочаяТаблица.Удалить(найдСтр[к]);
	КонецЦикла;
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры

Процедура Кнопка2Нажатие(Элемент)
	СформироватьРабочуюТаблицу();
	РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению",Истина));
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры
Показать


Результаты в ВАШУ пользу

вариант 2 - скажем так вот выглядит

Процедура СформироватьРабочуюТаблицу()
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ПриходТовары.Ссылка,
	|	ПриходТовары.НомерСтроки,
	|	ПриходТовары.Номенклатура,
	|	ПриходТовары.Склад,
	|	ПриходТовары.Контрагент,
	|	ПриходТовары.ДоговорКонтрагента,
	|	ПриходТовары.Партия,
	|	ПриходТовары.Количество,
	|	ПриходТовары.ЦенаПоставки,
	|	ПриходТовары.Сумма,
	|	ПриходТовары.НаценкаОпт,
	|	ПриходТовары.НаценкаРозн,
	|	ПриходТовары.КодКБ,
	|	ЛОЖЬ КАК КУдалению
	|ИЗ
	|	Документ.Приход.Товары КАК ПриходТовары
	|ГДЕ
	|	ПриходТовары.Ссылка.Дата МЕЖДУ &Дата1 И &Дата2";
	Запрос.УстановитьПараметр("Дата1", НачалоГода(ТекущаяДата()));
	Запрос.УстановитьПараметр("Дата2", ТекущаяДата());
	
	РабочаяТаблица = Запрос.Выполнить().Выгрузить();
	
	Счетчик = 1;
	Для каждого ТС из РабочаяТаблица Цикл
		Если Счетчик = 1 Тогда
			ТС.КУдалению = Истина;
			Счетчик = 0;
		Иначе
			Счетчик = 1;
		КонецЕсли;
	КонецЦикла;
	
	РабочаяТаблица.Индексы.Добавить("КУдалению");
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры

Процедура Кнопка1Нажатие(Элемент)
	СформироватьРабочуюТаблицу();
	найдСтр = РабочаяТаблица.НайтиСтроки(Новый Структура("КУдалению",Истина));
	Для к = 0 По найдСтр.ВГраница() Цикл
		РабочаяТаблица.Удалить(найдСтр[к]);
	КонецЦикла;
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры

Процедура Кнопка2Нажатие(Элемент)
	СформироватьРабочуюТаблицу();
	РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению",Истина));
	Сообщить(РабочаяТаблица.Количество());
КонецПроцедуры
Показать


результаты в МОЮ пользу
30. Marik 76 13.04.18 08:51 Сейчас в теме
(28)
ТекущаяУниверсальнаяДатаВМиллисекундах


я тестирую на 1С 8.1 и смотрю через замер производительности
31. Marik 76 13.04.18 08:56 Сейчас в теме
(28)
Опять же по поводу как формируется ТЗ. ТЗ можно формировать по разному, но вот удалить строки, как автор утверждает - быстрее всего ТАК!

Ремарка к "Это шутка! Не смешно"

Я тз к удалению подаю через запрос.

69. Быстрое удаление строк в таблице значений
Удаление строк в таблице значений

Быстрее всего удаляются строки путем копирования оставшихся строк по условию, обратному к условию удаления:

РабочаяТаблица = РабочаяТаблица.Скопировать(Новый Структура("КУдалению", Ложь))
32. Marik 76 13.04.18 09:19 Сейчас в теме
(28)

ОШИБОЧКА У меня :) я неправильно выполнял тесты. Сейчас вижу, что был неправ!

ВЫ правы коллега, я перепроверил еще раз - метод Автора быстрее.

В споре рождается истина - рад был поспорить с вами.

Единственно, все еще пока сомневаюсь - это расход ОЗУ.

Со всем уважением!
25. Marik 76 12.04.18 10:04 Сейчас в теме
(23)
Порадовало :) автор пишет, что:

Быстрее всего удаляются строки путем копирования оставшихся строк по условию, обратному к условию удаления


которое оказывается на самом деле - это:

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


Ну и конечно напоследок

Но последнее предложение должно пониматься нормальным разработчиком по-умолчанию

Я бы дописал

Нормальные разработчики
- это разработчики, у которых есть телепатическая супер сила. Это шутка :)! Да, я прочитал ссылку выше к задаче 69. И все равно считаю, что удалить моим способ быстрее и самое главнее надежнее. Представьте у вас в ТЗ ярды строк, способ предложенный автором на короткое время создаст 2 копии ТЗ с 2-кратным потреблением ОЗУ (на 1-ю и 2-ю ТЗ), потом конечно 1-я удалится. Но что если у вас ОЗУ на 2 ТЗ не хватит? Получите банально "Недостаточно памяти".

Со всем уважением!
33. pavlovsv 08.05.18 16:46 Сейчас в теме
Спасибо автору за интересные публикации.
Хочу поделиться своей версией минимализма для задачи 57:

ВЫБРАТЬ ПЕРВЫЕ 1
КурсыВалют.Период,
КурсыВалют.Валюта,
КурсыВалют.Курс
ИЗ
РегистрСведений.КурсыВалют КАК КурсыВалют
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
МАКСИМУМ(КурсыВалют.Период) КАК Период,
&ВалютаСсылка КАК Валюта
ИЗ
РегистрСведений.КурсыВалют КАК КурсыВалют
ГДЕ
КурсыВалют.Валюта = &ВалютаСсылка) КАК МаксПериодКурсаВалюты
ПО (МаксПериодКурсаВалюты.Период > КурсыВалют.Период)
И (МаксПериодКурсаВалюты.Валюта = КурсыВалют.Валюта)

УПОРЯДОЧИТЬ ПО
КурсыВалют.Период УБЫВ

Протестировал оба варианта на таблице из 65 тысяч записей, этот вариант отрабатывает в два раза быстрее.
34. caponid 20.09.18 19:27 Сейчас в теме
Опять просмотрел все статьи... как всегда очень интересно, а местами забавно)
но что то меня начали пугать "минимализмы" в запросах....

Могу добавить в копилку: Знак числа
Знак = (Ч>0)-(Ч<0) //1,0,-1
35. triviumfan 91 19.11.18 14:39 Сейчас в теме
70. Это точно работает?Если в переменных start и end задать "с 8 до 9", а с 9 до 10 интервал существует, то условие некорректно
ГДЕ
	(РАЗНОСТЬДАТ(ЗаписиНаРемонт.НачалоВыполнения, &НачальныйИнтервал, СЕКУНДА) * РАЗНОСТЬДАТ(&КонечныйИнтервал, ЗаписиНаРемонт.НачалоВыполнения, СЕКУНДА) * РАЗНОСТЬДАТ(&КонечныйИнтервал, &НачальныйИнтервал, СЕКУНДА) <= 0
			ИЛИ РАЗНОСТЬДАТ(ЗаписиНаРемонт.НачалоВыполнения, &НачальныйИнтервал, СЕКУНДА) * РАЗНОСТЬДАТ(ЗаписиНаРемонт.ОкончаниеВыполнения, &НачальныйИнтервал, СЕКУНДА) * РАЗНОСТЬДАТ(ЗаписиНаРемонт.ОкончаниеВыполнения, ЗаписиНаРемонт.НачалоВыполнения, СЕКУНДА) >= 0)
36. ildarovich 7844 19.11.18 15:28 Сейчас в теме
(35) Тестировал в свое время достаточно внимательно, работать должно
sel ect * fr om tab
where (@start - start) * (start - @end) * (@start - @end) <= 0 
      or (@start - start) * (@start - end) * (start - end) >= 0;

ГДЕ
    (РАЗНОСТЬДАТ(ЗаписиНаРемонт.НачалоВыполнения, &НачальныйИнтервал, СЕКУНДА) * РАЗНОСТЬДАТ(&КонечныйИнтервал, ЗаписиНаРемонт.НачалоВыполнения, СЕКУНДА) * РАЗНОСТЬДАТ(&КонечныйИнтервал, &НачальныйИнтервал, СЕКУНДА) <= 0
            ИЛИ РАЗНОСТЬДАТ(ЗаписиНаРемонт.НачалоВыполнения, &НачальныйИнтервал, СЕКУНДА) * РАЗНОСТЬДАТ(ЗаписиНаРемонт.ОкончаниеВыполнения, &НачальныйИнтервал, СЕКУНДА) * РАЗНОСТЬДАТ(ЗаписиНаРемонт.ОкончаниеВыполнения, ЗаписиНаРемонт.НачалоВыполнения, СЕКУНДА) >= 0)

start = ЗаписиНаРемонт.НачалоВыполнения = 8 
end = ЗаписиНаРемонт.ОкончаниеВыполнения = 9
@start = &НачальныйИнтервал = 9
@end = &КонечныйИнтервал = 10

Следовательно,
РАЗНОСТЬДАТ(ЗаписиНаРемонт.ОкончаниеВыполнения, &НачальныйИнтервал, СЕКУНДА) == 0

Вторая часть условия выполнится и из-за "или" станет истинным все условие.
Получится, что интервалы пересеклись.
Если хотите, чтобы они не пересекались, задайте значения
end = ЗаписиНаРемонт.ОкончаниеВыполнения = 8:59:59, тогда у интервалов не будет общей секунды.
37. triviumfan 91 19.11.18 16:40 Сейчас в теме
(36) Неудобно отнимать секунду...
Пришлось воспользоваться этой темой (где я также и ваше решение увидел в комментах).
Заменил на
ГДЕ
	(ЗаписиНаРемонт.НачалоВыполнения >= &НачальныйИнтервал
				И ЗаписиНаРемонт.НачалоВыполнения < &КонечныйИнтервал
			ИЛИ ЗаписиНаРемонт.ОкончаниеВыполнения <= &КонечныйИнтервал
				И ЗаписиНаРемонт.ОкончаниеВыполнения > &НачальныйИнтервал
			ИЛИ ЗаписиНаРемонт.НачалоВыполнения < &КонечныйИнтервал
				И ЗаписиНаРемонт.ОкончаниеВыполнения > &НачальныйИнтервал
			ИЛИ ЗаписиНаРемонт.НачалоВыполнения >= &НачальныйИнтервал
				И ЗаписиНаРемонт.ОкончаниеВыполнения <= &КонечныйИнтервал)
Показать

из первого примера:

SET @start:=4;
SET @end:=8;
SEL ECT * FR OM `table`
WHERE
(`start` >= @start AND `start` < @end) /*смещение вперед*/
OR
(`end` <= @end AND `end` > @start) /*смещение назад*/
OR
(`start` < @end AND `end` > @start) /*вхождение - на самом деле здесь не обязательно оно обработается одним из предыдущих выражений*/
OR
(`start` >= @start AND `end` <= @end)/*поглощение и совпадение*/
Показать
38. prime9 1157 18.01.19 13:10 Сейчас в теме
Очень полено, спасибо :)
39. пользователь 12.02.19 08:54
Сообщение было скрыто модератором.
...
40. evgeni-red 86 12.02.19 08:56 Сейчас в теме
Спасибо! (51. Объединение пересекающихся периодов в запросе) - очень помогло для слияния периодов в запросе!
41. trustasia 14 22.03.19 09:04 Сейчас в теме
Работаю над задачей определения "находится ли геоточка внутри геополигона". Вроде нашел новое решение, хотел с Вами связаться, обсудить. Пока тестирую в реальном времени. Не гуглом и не Постгри, их таинственные методы не описаны.
42. ildarovich 7844 22.03.19 12:21 Сейчас в теме
(41) Это интересно, готов к обсуждению
43. caponid 29.05.19 17:05 Сейчас в теме
44. Убрать префикс и лидирующие нули из номера
Функция ЧислоСправа1("ДП 046464") 
ломается с эксепшином Преобразование значения к типу Число не может быть выполнено.
Номер содержит пробелы.
44. ildarovich 7844 29.05.19 23:14 Сейчас в теме
(43) Да, на пробелы в номере (?) или последний пробел в "префиксе" этот вариант не рассчитан. А, по вашему, должен был?
45. caponid 30.05.19 13:22 Сейчас в теме
(44) Пробелы в номере - это уже не номер) - или должен обговариваться как исключение.
А вот пробел в префиксе (он же может быть произвольным) - это вполне нормально.

Так что я за универсальность, и против ограничений (из-за неполноты решения) на входные данные.
46. n_i_k1966 12.05.20 13:49 Сейчас в теме
СтрСоединить(СтрРазделить(СтрокаСЦифрами, СтрСоединить(СтрРазделить(СтрокаСЦифрами, "0123456789"))))

Если строка с цифрами содержит только цифры - результат пустой
47. naf2000 28.04.21 00:36 Сейчас в теме
69. Быстрее всего удаляются строки путем копирования оставшихся строк по условию, обратному к условию удаления

Это если ссылок на таблицу в других объектах нет. Иначе получим новый правильный экземпляр, а ссылки в других местах будут вести на старую копию таблицы.
48. tolyan_ekb 104 08.06.21 14:08 Сейчас в теме
№48. "Разбиение произвольного периода на интервалы в запросе" с отработкой варианта когда не нужно разбиение, т.к. период мал . Не понимаю как реализовать в запросе. Подскажите пожалуйста.
Оставьте свое сообщение