Запрос, установить дату когда цена впервые непрерывно была установлена равной текущей
Добрый день!
УТ 10.3.8.9 сильно изменённая, платформа 8.3.16.1063
В механизме печати ценников имеется процедура, добавляющая в таблицу товаров дату, когда была установлена цена номенклатуры.
Часто, документ устанавливает цену, равную установленной ранее цене (равную действующей цене). В этом случае, ценник на печать не выводится. Однако, затем среди кассиров происходят разборки, для установления и поругания того, кто не распечатал ценник. В ценнике же печатается дата последней установки цены номенклатуры, а не дата когда цена впервые (без прерывания) была установлена равной текущей.
Прошу помочь составить запрос для получения требуемой даты.
Единственное, что пока сделал
Однако , этот код показывает цену, которая была задолго до нужной даты (цена менялась после этого, и снова стала равной выведенной дате). И в таблице значений (используется в качестве параметра) будет множество дат, весьма вероятно, то цены перепутаются между разной номенклатуры. Не хочется делать запрос в цикле, или обращаться к основной таблице регистра сведений.
УТ 10.3.8.9 сильно изменённая, платформа 8.3.16.1063
В механизме печати ценников имеется процедура, добавляющая в таблицу товаров дату, когда была установлена цена номенклатуры.
Процедура УстановитьДатыУстановокЦен(ТаблицаТоваров)
ТабТо = ТаблицаТоваров.Скопировать(,"Номенклатура");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Номенклатура,
| ЦеныНоменклатурыСрезПоследних.Период
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| ,
| ТипЦен = &ТипЦен
| И Номенклатура В (&Номенклатура)) КАК ЦеныНоменклатурыСрезПоследних";
Запрос.УстановитьПараметр("Номенклатура", ТабТо);
Запрос.УстановитьПараметр("ТипЦен", ТипЦены);
ТЗДатыЦен = Запрос.Выполнить().Выгрузить();
КонецПроцедуры
ПоказатьЧасто, документ устанавливает цену, равную установленной ранее цене (равную действующей цене). В этом случае, ценник на печать не выводится. Однако, затем среди кассиров происходят разборки, для установления и поругания того, кто не распечатал ценник. В ценнике же печатается дата последней установки цены номенклатуры, а не дата когда цена впервые (без прерывания) была установлена равной текущей.
Прошу помочь составить запрос для получения требуемой даты.
Единственное, что пока сделал
ВЫБРАТЬ
ЦеныНоменклатурыСрезПервых.Номенклатура,
ЦеныНоменклатурыСрезПервых.Период,
ЦеныНоменклатурыСрезПервых.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПервых(
,
ТипЦен = &ТипЦен
И Номенклатура В (&Номенклатура)
И Цена В
(ВЫБРАТЬ
ЦеныНоменклатурыСрезПоследних.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ТипЦен = &ТипЦен
И Номенклатура В (&Номенклатура)) КАК ЦеныНоменклатурыСрезПоследних)) КАК ЦеныНоменклатурыСрезПервых
ПоказатьОднако , этот код показывает цену, которая была задолго до нужной даты (цена менялась после этого, и снова стала равной выведенной дате). И в таблице значений (используется в качестве параметра) будет множество дат, весьма вероятно, то цены перепутаются между разной номенклатуры. Не хочется делать запрос в цикле, или обращаться к основной таблице регистра сведений.
Прикрепленные файлы:
Найденные решения
(18) Предыдущее значение и дату в 1С найти просто, но от этого конечно воротит :-)
1. Соединяете таблицу саму с собой и находите для каждой даты максимальную дату, но меньшую текущей. В вашей задаче можно не саму с собой соединять, а к отфильтрованной таблице цеплять все движения. Максимальная дата это и есть предыдущая дата.
2. К полученной таблице: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата> необходимо ещё раз прицепить все движения по: номенклатура, предыдущая дата и вытащить от туда предыдущую цену.
В итоге у вас получается таблица: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата>, <предыдущая цена>
Далее я так понимаю всё понятно.
1. Соединяете таблицу саму с собой и находите для каждой даты максимальную дату, но меньшую текущей. В вашей задаче можно не саму с собой соединять, а к отфильтрованной таблице цеплять все движения. Максимальная дата это и есть предыдущая дата.
2. К полученной таблице: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата> необходимо ещё раз прицепить все движения по: номенклатура, предыдущая дата и вытащить от туда предыдущую цену.
В итоге у вас получается таблица: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата>, <предыдущая цена>
Далее я так понимаю всё понятно.
(18) у меня такой запрос получился
выбрать //первые 1000
Таб.Номенклатура,
таб.Цена,
таб.Период
Поместить Пром
из
регистрСведений.ЦеныНоменклатуры.СрезПоследних(,ВидЦены = &ВидЦены) таб
//где
//Таб.ВидЦены = &ВидЦены
//и Год(таб.Период) = 2022
//упорядочить по
//Таб.Номенклатура
;
выбрать
пром.Номенклатура,
Максимум(таб.Период) как Период
Поместить ПромМакс
из пром
левое соединение регистрСведений.ЦеныНоменклатуры таб
по Таб.ВидЦены = &ВидЦены
и Таб.Номенклатура = Пром.Номенклатура
и Таб.Цена <> Пром.Цена
и Таб.Период < Пром.Период
где
таб.Период есть не null
сгруппировать по
пром.Номенклатура
;
выбрать
пром.Номенклатура,
Минимум(таб.Период) как ПериодДо
Поместить ПромМин
из проммакс пром
левое соединение регистрСведений.ЦеныНоменклатуры таб
по Таб.ВидЦены = &ВидЦены
и Таб.Номенклатура = Пром.Номенклатура
и Таб.Период > Пром.Период
где
таб.Период есть не null
сгруппировать по
пром.Номенклатура
;
Выбрать
пром.*,
таб.ПериодДо
из пром
левое соединение ПромМин таб
по Таб.Номенклатура = Пром.Номенклатура
где
Пром.Период <> таб.ПериодДо
упорядочить по
пром.Номенклатура
ПоказатьОстальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(1)
Не совсем понятно объяснение, т.к. СрезПоследних дает именно последнюю дату установки цены
Вы хотите получить дату предыдущей установленной цены?
В ценнике же печатается дата последней установки цены номенклатуры, а не дата когда цена впервые (без прерывания) была установлена равной текущей.
Не совсем понятно объяснение, т.к. СрезПоследних дает именно последнюю дату установки цены
Вы хотите получить дату предыдущей установленной цены?
(5)ТСу нужна дата, когда текущую цену установили. Типа 1 марта поставили 500 рублей, потом 2 и 3 марта тоже поставили цену 500 рублей. Нужно получить дату 1 марта.
(1) Я могу ошибаться конечно, но в типовых вроде в таком случае вообще движение по регистрам цен не делается, если цена не поменялась, и задача автоматически решается. Может вам тоже в эту сторону посмотреть вместо того, чтобы извращаться с запросами?
(1) Я могу ошибаться конечно, но в типовых вроде в таком случае вообще движение по регистрам цен не делается, если цена не поменялась, и задача автоматически решается. Может вам тоже в эту сторону посмотреть вместо того, чтобы извращаться с запросами?
(16) Как тут ещё подробнее. У тебя таблица из номенклатуры и цены текущей. Это фильтр. Для всех движений цены по этому фильтру находишь предыдущее значение. Предыдущее значение ищется по всем движениям без фильтра.
Как найти предыдущее значение думаю нет сложностей. В стандартном SQL это функция LAG(), в 1С это несколько джоинов.
Далее берешь только те, где цена НЕ совпадает. Среди них находишь максимальную дату. Усё.
Если бы 1С поддерживала рекурсивные запросы как все СУБД, которые 1С использует, то было бы ещё проще.
Как найти предыдущее значение думаю нет сложностей. В стандартном SQL это функция LAG(), в 1С это несколько джоинов.
Далее берешь только те, где цена НЕ совпадает. Среди них находишь максимальную дату. Усё.
Если бы 1С поддерживала рекурсивные запросы как все СУБД, которые 1С использует, то было бы ещё проще.
(18)
Есть ещё проще способ найти предыдущую запись в 1С. Но я не помню с какого релиза платформы АвтоНомерЗаписи() в 1С появился. У вас 16-й. Достаточно старый.
Если у вас row_number() уже доступна, то нумеруйте все записи.
Укажите ВЫБРАТЬ ПЕРВЫЕ 999...99 и УПОРЯДОЧИТЬ ПО номенклатура, период.
В 1С, с какого-то перепуга, нельзя просто пронумеровать записи, указав требуемую сортировку, не указав SELECT TOP (MS SQL) или SELECT LIMIT (PsgSQL). Откуда они это придумали не знаю, но это так. В СУБД таких ограничений нет.
Далее соединяете таблицу саму с собой по условию WHERE т1.номенклатура = т2.номенклатура and т1.нпп = т2.нпп+1
Собственно всё.
У меня весь вопрос про то, как найти предыдущее значение
Есть ещё проще способ найти предыдущую запись в 1С. Но я не помню с какого релиза платформы АвтоНомерЗаписи() в 1С появился. У вас 16-й. Достаточно старый.
Если у вас row_number() уже доступна, то нумеруйте все записи.
Укажите ВЫБРАТЬ ПЕРВЫЕ 999...99 и УПОРЯДОЧИТЬ ПО номенклатура, период.
В 1С, с какого-то перепуга, нельзя просто пронумеровать записи, указав требуемую сортировку, не указав SELECT TOP (MS SQL) или SELECT LIMIT (PsgSQL). Откуда они это придумали не знаю, но это так. В СУБД таких ограничений нет.
Далее соединяете таблицу саму с собой по условию WHERE т1.номенклатура = т2.номенклатура and т1.нпп = т2.нпп+1
Собственно всё.
(18) Предыдущее значение и дату в 1С найти просто, но от этого конечно воротит :-)
1. Соединяете таблицу саму с собой и находите для каждой даты максимальную дату, но меньшую текущей. В вашей задаче можно не саму с собой соединять, а к отфильтрованной таблице цеплять все движения. Максимальная дата это и есть предыдущая дата.
2. К полученной таблице: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата> необходимо ещё раз прицепить все движения по: номенклатура, предыдущая дата и вытащить от туда предыдущую цену.
В итоге у вас получается таблица: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата>, <предыдущая цена>
Далее я так понимаю всё понятно.
1. Соединяете таблицу саму с собой и находите для каждой даты максимальную дату, но меньшую текущей. В вашей задаче можно не саму с собой соединять, а к отфильтрованной таблице цеплять все движения. Максимальная дата это и есть предыдущая дата.
2. К полученной таблице: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата> необходимо ещё раз прицепить все движения по: номенклатура, предыдущая дата и вытащить от туда предыдущую цену.
В итоге у вас получается таблица: <Номенклатура>, <дата цены>, <цена>, <предыдущая дата>, <предыдущая цена>
Далее я так понимаю всё понятно.
(18) у меня такой запрос получился
выбрать //первые 1000
Таб.Номенклатура,
таб.Цена,
таб.Период
Поместить Пром
из
регистрСведений.ЦеныНоменклатуры.СрезПоследних(,ВидЦены = &ВидЦены) таб
//где
//Таб.ВидЦены = &ВидЦены
//и Год(таб.Период) = 2022
//упорядочить по
//Таб.Номенклатура
;
выбрать
пром.Номенклатура,
Максимум(таб.Период) как Период
Поместить ПромМакс
из пром
левое соединение регистрСведений.ЦеныНоменклатуры таб
по Таб.ВидЦены = &ВидЦены
и Таб.Номенклатура = Пром.Номенклатура
и Таб.Цена <> Пром.Цена
и Таб.Период < Пром.Период
где
таб.Период есть не null
сгруппировать по
пром.Номенклатура
;
выбрать
пром.Номенклатура,
Минимум(таб.Период) как ПериодДо
Поместить ПромМин
из проммакс пром
левое соединение регистрСведений.ЦеныНоменклатуры таб
по Таб.ВидЦены = &ВидЦены
и Таб.Номенклатура = Пром.Номенклатура
и Таб.Период > Пром.Период
где
таб.Период есть не null
сгруппировать по
пром.Номенклатура
;
Выбрать
пром.*,
таб.ПериодДо
из пром
левое соединение ПромМин таб
по Таб.Номенклатура = Пром.Номенклатура
где
Пром.Период <> таб.ПериодДо
упорядочить по
пром.Номенклатура
Показать
(20) Действительно, ваш запрос работает спасибо!
ВЫБРАТЬ
таб.Номенклатура,
таб.Цена,
таб.Период
ПОМЕСТИТЬ Пром
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
,
ТипЦен = &ВидЦены
И Номенклатура В (&Номенклатура)) КАК таб
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
пром.Номенклатура,
МАКСИМУМ(таб.Период) КАК Период
ПОМЕСТИТЬ ПромМакс
ИЗ
Пром КАК пром
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК таб
ПО (таб.ТипЦен = &ВидЦены)
И (таб.Номенклатура = пром.Номенклатура)
И (таб.Цена <> пром.Цена)
И (таб.Период < пром.Период)
ГДЕ
таб.Период ЕСТЬ НЕ NULL
СГРУППИРОВАТЬ ПО
пром.Номенклатура
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
пром.Номенклатура,
МИНИМУМ(таб.Период) КАК ПериодДо
ПОМЕСТИТЬ ПромМин
ИЗ
ПромМакс КАК пром
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК таб
ПО (таб.ТипЦен = &ВидЦены)
И (таб.Номенклатура = пром.Номенклатура)
И (таб.Период > пром.Период)
ГДЕ
таб.Период ЕСТЬ НЕ NULL
СГРУППИРОВАТЬ ПО
пром.Номенклатура
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
пром.Номенклатура,
пром.Цена,
пром.Период,
таб.ПериодДо
ИЗ
Пром КАК пром
ЛЕВОЕ СОЕДИНЕНИЕ ПромМин КАК таб
ПО (таб.Номенклатура = пром.Номенклатура)
ГДЕ
пром.Период <> таб.ПериодДо
УПОРЯДОЧИТЬ ПО
пром.Номенклатура
Показать
(18) Ниже набросал запрос на SQLite, который находит для каждой номенклатуры на входе фактическую дату установки последней цены.
Тут я не стал срез собирать и по нему фильтры устраивать. Сделал просто для всех номенклатур и только поиск этой фактической даты установки последней цены.
Запрос крайне короткий и понятный.
Тут я не стал срез собирать и по нему фильтры устраивать. Сделал просто для всех номенклатур и только поиск этой фактической даты установки последней цены.
Запрос крайне короткий и понятный.
WITH vt_data as (
sel ect 'Номенклатура1' as p, strftime('2022-01-17T00:00:00.000') as d, 100 as c
UNI ON ALL sel ect 'Номенклатура1', strftime('2022-01-19T00:00:00.000'), 90
UNI ON ALL select 'Номенклатура1', strftime('2022-01-207T00:00:00.000'), 100
UNI ON ALL select 'Номенклатура1', strftime('2022-01-21T00:00:00.000'), 110
UNI ON ALL sel ect 'Номенклатура1', strftime('2022-01-23T00:00:00.000'), 100
UNION ALL sel ect 'Номенклатура1', strftime('2022-01-27T00:00:00.000'), 100
UNION ALL sel ect 'Номенклатура2', strftime('2022-01-17T00:00:00.000'), 200
UNION ALL sel ect 'Номенклатура2', strftime('2022-01-18T00:00:00.000'), 220
UNION ALL sel ect 'Номенклатура2', strftime('2022-01-19T00:00:00.000'), 200
UNION ALL sel ect 'Номенклатура2', strftime('2022-01-22T00:00:00.000'), 200
UNION ALL sel ect 'Номенклатура2', strftime('2022-01-29T00:00:00.000'), 200
UNION ALL sel ect 'Номенклатура3', strftime('2022-01-15T00:00:00.000'), 300
UNION ALL sel ect 'Номенклатура3', strftime('2022-01-19T00:00:00.000'), 300
)
SEL ECT
t.p
,MAX(iif(t.c = t.pred_c, null, t.d)) as pred_d
fr om
(SEL ECT
t.p as p
,t.d as d
,t.c as c
,LAG(t.c) over(partition by t.p ORDER by t.d) as pred_c
FR OM
vt_data as t
) as t
group by
t.p
На выходе:
p pred_d
------------------------------------------------
Номенклатура1 2022-01-23
Номенклатура2 2022-01-19
Номенклатура3 2022-01-15
Показать
(22) Спасибо!!
Получилось вот так:
Получилось вот так:
ВЫБРАТЬ
ЦеныНоменклатуры.Номенклатура,
ЦеныНоменклатуры.Период КАК Период,
ЦеныНоменклатуры.Цена
ПОМЕСТИТЬ ВТ_ВсеЦены
ИЗ
РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ГДЕ
ЦеныНоменклатуры.ТипЦен = &ТипЦен
И ЦеныНоменклатуры.Номенклатура В(&Номенклатура)
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
ВТ_ВсеЦены.Номенклатура КАК Номенклатура,
МАКСИМУМ(ВТ_ВсеЦены.Период) КАК Период
ПОМЕСТИТЬ ВТ_ДатыПредыдущейЦены
ИЗ
ВТ_ВсеЦены КАК ВТ_ВсеЦены
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ПО ВТ_ВсеЦены.Номенклатура = ЦеныНоменклатуры.Номенклатура
И ВТ_ВсеЦены.Цена <> ЦеныНоменклатуры.Цена
И ВТ_ВсеЦены.Период < ЦеныНоменклатуры.Период
ГДЕ
ЦеныНоменклатуры.ТипЦен = &ТипЦен
И ЦеныНоменклатуры.Номенклатура В(&Номенклатура)
СГРУППИРОВАТЬ ПО
ВТ_ВсеЦены.Номенклатура
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
ВТ_ВсеЦены.Номенклатура,
МИНИМУМ(ВТ_ВсеЦены.Период) КАК Период
ИЗ
ВТ_ВсеЦены КАК ВТ_ВсеЦены
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ДатыПредыдущейЦены КАК ВТ_ДатыПредыдущейЦены
ПО ВТ_ВсеЦены.Номенклатура = ВТ_ДатыПредыдущейЦены.Номенклатура
И ВТ_ВсеЦены.Период > ВТ_ДатыПредыдущейЦены.Период
СГРУППИРОВАТЬ ПО
ВТ_ВсеЦены.Номенклатура
Показать
(24) Кто 1С мешает отказаться от файловой базы и использовать PsgSQL? Маркетологи?
Опять же в файловой рисуют программисты 1С. Кто им мешает сделать единообразно как в СУБД?
Кто им мешает внутри использовать тот же SQLite, а не изобретать свой велосипед?
В 1С++ 77 файловые давно такая возможность есть и именно через SQLite - более 10-ти лет точно.
Ответ: никто не мешает.
Поэтому и пишу - откуда они это придумали - не знаю. Это их личная инициатива придумать себе палки в колеса.
Опять же в файловой рисуют программисты 1С. Кто им мешает сделать единообразно как в СУБД?
Кто им мешает внутри использовать тот же SQLite, а не изобретать свой велосипед?
В 1С++ 77 файловые давно такая возможность есть и именно через SQLite - более 10-ти лет точно.
Ответ: никто не мешает.
Поэтому и пишу - откуда они это придумали - не знаю. Это их личная инициатива придумать себе палки в колеса.
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот