gifts2017

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

Опубликовал Николай Крылов (Nikola23) в раздел Программирование - Практика программирования

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

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

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

     
Период Валюта Курс
10.03.2010 Тест2 12,0000
12.03.2010 Тест2 142,0000
15.03.2010 Тест2 100,0000
16.03.2010 Тест 20,0000
19.03.2010 Тест2 213,0000
20.03.2010 Тест 40,0000

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

Далее собственно запрос:

ВЫБРАТЬ
    КурсыВалют.Курс КАК Курс2,
    КурсыВалют.Период КАК Период2
ПОМЕСТИТЬ Курсы2
ИЗ
    РегистрСведений.КурсыВалют КАК КурсыВалют
ГДЕ
    КурсыВалют.Валюта.Наименование = "Тест2"
;

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

А вот результат выполнения запроса:

       
Курс1 Период1 Курс2 Период2
20,0000 16.03.2010 100,0000 15.03.2010
40,0000 20.03.2010 213,0000 19.03.2010

т.е. я получил значение курса второй валюты действовавшее на дату периода установки курса первой валюты.

 

 

 

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Котэ Пруидзе (kote) 21.03.10 15:46
Это то же, что и 2 среза последних на 2ве даты что ли?
Не очень понятно, что это даёт.. дайте пожалуйста пару примеров где это может пригодится..
3. Николай Крылов (Nikola23) 21.03.10 18:22
ту 1:
В конкретно этом примере, действительно можно было бы использовать 2 среза последних, однако мне попадались ситуации, когда в запросе необходимо было получить значения периодического регистра сведений или остатков из регистра накопления на различные, заранее не известные наборы дат. Ранее приходилось решать динамическим построением текста запроса.

Пример по другим таблицам, но с использованием того же механизма.
Например используя этот механизм можно построить отчет "Динамика дебиторской задолженности по месяцам" для БП8 в различных валютах. Причем сумма задолженности вычисляется по курсу, действовавшему на конец каждого месяца попавшего в период отчета.
4. Ivon (Ivon) 24.03.10 10:55
Вот здесь http://infostart.ru/public/21181/ моя статья с примером-базой, посвященная данному вопросу. Твое решение сильно запутано. Там надо всего 2 запроса: либо один вложенный в другой, либо через одну временную таблицу. У тебя же в примере запросов 4.
5. Николай Крылов (Nikola23) 24.03.10 11:21
При желании можно сделать текст этого запроса и с 2мя конструкциями выбор и с 3мя.
Некоторая запутанность обусловлена тем, что я использую 2 периодических регистра сведений.
Как не странно, но с 4мя запросами этот пример отрабатывает приблизительно в 10 раз быстрее, чем с 2мя.))))
6. Ivon (Ivon) 24.03.10 12:47
(5) В данном примере я увидел только РегистрСведений.КурсыВалют. Где второй? На самом деле скорость выполнения так же обусловлена построением запроса и его оптимизацией внутри MSSQL. Как сервер оптимизирует запрос - одному Майкрософту известно, но не факт, что он это делает всегда правильно. Конструкции с вложенным запросом и с временной таблицей могут различаться по времени выполнения в разные стороны из-за многих факторов, которые включают в себя так же и то, насколько правильно настроен MSSQL и количество данных, передаваемых между таблицами. Так что быстрее в 10 раз может быть исключительно на твоей системе, а у других может быть так же или медленнее.
7. Ivon (Ivon) 24.03.10 12:49
(1). Посмотрите мою статью, указанную в 4-м посте, возможно так Вам станет понятнее. На самом деле нужный и полезный прием.
8. Николай Крылов (Nikola23) 24.03.10 13:25
(7). указанную статью я видел уже давно.
На мой взгляд - и эта и Ваша статья - одно и тоже, да вот только когда надо я не смог найти уже предложенное Вами решение моего вопроса. Потому сначала сделал сам, а потом выложил на этом сайте.
Предлагаю не начинать обсуждение, чем хорошо ваше решение, или чем хорошо мое - смысла я в этом не вижу. Если лучше все таки Ваше - честь Вам и хвала.
Честно говоря, Ваше решение кажется мне не менее запутанным, чем мое))).
9. Ivon (Ivon) 24.03.10 14:51
(8) Посмотреть статью было адресовано kote.
10. Николай Крылов (Nikola23) 24.03.10 15:09
11. Александр Крынецкий (echo77) 02.02.12 21:37
Уже было. Это называется срез последних на каждую дату в запросе. Например, вот эта публикация http://infostart.ru/public/77568/
В интернете уже достаточно решений данного вопроса.
А соединять два набора данных в СКД с исползованием среза последних - я не рекомендую, т.к. это достаточно медленно работает

(1) Где это можно применить? Например, вы делаете реестр счетов-фактур, часть из которых не рублевые, а валютные. Вам нужен реестр в одной валюте - в рублях. По скольку курсы валют могут быть не на каждую дату, а какие счет-фактуры и на какю дату в валюте сразу и не определишь.
12. Николай Крылов (Nikola23) 02.02.12 21:47
(11) echo77, Указанная Вами публикация датирована позже моей. Собственно, мне все-равно.

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

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

По прошествии времени, понимаю, что привел не всем понятный пример(
13. Александр Крынецкий (echo77) 03.02.12 06:55
(12) Я только что увидел, что я здесь некропостингом занимаюсь. Не понимаю, как ваша публикация 2010 года всплыла на главной странице...
14. Рус Иванов (Onemany) 12.07.12 17:03
Есть пример применения?
oneman@yandex.ru; +1 Ответить 1
15. Romeo (oneman@yandex.ru) 12.07.12 17:04
Обработка-пример имеется?
16. Николай Крылов (Nikola23) 12.07.12 17:29
(14), (15) Пример приведен в публикации. Это виртуальный пример. На практике этот кусок кода, обычно, является частью более крупного запроса.
17. Юрий Патласов (NoRazum) 27.09.12 15:54
Без примера очень сложно.
Реальный пример хотя бы из УТ