Имя: Пароль:
1C
 
Нужна помощь с запросом, не могу сообразить
,
0 Экхонок
 
09.03.17
22:58
Есть регистр сведений курс валют. Как написать запрос, чтобы он получал периоды, когда курс не менялся?
Например:
Таблица курсов валют в регистре

01.01.01    USD    50
02.01.01    USD    50
03.01.01    USD    50
04.01.01    USD    51
05.01.01    USD    50
06.01.01    USD    50
07.01.01    USD    52
01.01.01    EUR    65
02.01.01    EUR    65
03.01.01    EUR    64
04.01.01    EUR    63

Таблица результата
Дата начала    Дата окончания    Валюта    Курс
01.01.01    03.01.01    USD    50
04.01.01    04.01.01    USD    51
05.01.01    06.01.01    USD    50
07.01.01    07.01.01    USD    52
01.01.01    02.01.01    EUR    65
03.01.01    03.01.01    EUR    64
04.01.01    04.01.01    EUR    63

Написал запрос, но выводятся больше значений, чем надо. Не мойму, как убрать лишнее.

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

УПОРЯДОЧИТЬ ПО
    Валюта,
    ПериодНач,
    ПериодКон
1 Экхонок
 
09.03.17
22:59
У меня сейчас выводится:
01.01.2017    01.01.2017    EUR    65,0000
01.01.2017    02.01.2017    EUR    65,0000
02.01.2017    02.01.2017    EUR    65,0000
03.01.2017    03.01.2017    EUR    64,0000
04.01.2017    04.01.2017    EUR    63,0000
01.01.2017    01.01.2017    USD    50,0000
01.01.2017    02.01.2017    USD    50,0000
01.01.2017    03.01.2017    USD    50,0000
01.01.2017    05.01.2017    USD    50,0000
01.01.2017    06.01.2017    USD    50,0000
02.01.2017    02.01.2017    USD    50,0000
02.01.2017    03.01.2017    USD    50,0000
02.01.2017    05.01.2017    USD    50,0000
02.01.2017    06.01.2017    USD    50,0000
03.01.2017    03.01.2017    USD    50,0000
03.01.2017    05.01.2017    USD    50,0000
03.01.2017    06.01.2017    USD    50,0000
04.01.2017    04.01.2017    USD    51,0000
05.01.2017    05.01.2017    USD    50,0000
05.01.2017    06.01.2017    USD    50,0000
06.01.2017    06.01.2017    USD    50,0000
07.01.2017    07.01.2017    USD    52,0000

Как избавиться от лишнего? Я всё голову сломал.
2 EvgeniuXP
 
09.03.17
23:34
Кто запросом не умеет - тот циклом делает - главное результат :)
3 Экхонок
 
09.03.17
23:37
(2) стоит задача сделать это именно запросом. Циклом или обработкой результата, я б уже сделал. Как-то хитро соединения поставить, но не пойму какие условия должны быть.
4 qwertor
 
09.03.17
23:47
select    datetime(2001,01,01) период , "USD" валюта,  50 курс
into КурсыВалют
union all
select    datetime(2001,01,02) период , "USD" валюта,  50 курс
union all
select    datetime(2001,01,03) период , "USD" валюта,  50 курс
union all
select    datetime(2001,01,04) период , "USD" валюта,  51 курс
union all
select    datetime(2001,01,05) период , "USD" валюта,  50 курс
union all
select    datetime(2001,01,06) период , "USD" валюта,  50 курс
union all
select    datetime(2001,01,07) период , "USD" валюта,  52 курс
union all
select    datetime(2001,01,08) период , "USD" валюта,  54 курс  // следующий перид или фильтром
union all
select    datetime(2000,12,31) период , "USD" валюта,  00 курс  //прошлые периоды или фильтр добавить в запрос по дате

;

select k1.*, k2.Курс    Курс2 , k2.Период    Период2
into КурсИзменения
   from  КурсыВалют k1
  inner join  КурсыВалют k2 on k1.Валюта = k2.Валюта and k1.Период = dateadd(k2.Период,day,-1) and  k1.Курс <> k2.Курс
;

select  max(kd2.Период2) ДатаНачала , kd1.период ДатаОкончания,kd1.Валюта,kd1.Курс,  max(kd2.Период2) п2 from  КурсИзменения kd1
  inner join   КурсИзменения  kd2 on  kd1.Валюта = kd2.Валюта and kd1.Период >  kd2.Период
group by kd1.период,kd1.Валюта,kd1.Курс  
order by    kd1.Период

// ну как-то так, идею поймешь дальше дайдешь
5 yzimin
 
10.03.17
00:13
Можно просто соединить календарь выходные и праздничные дни с регистром по курсам валют - это и будут дни, когда курс не менялся)))
6 Живой Ископаемый
 
10.03.17
00:22
7 Fram
 
10.03.17
01:31
как то так

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

функции писал на память, если что
8 Fram
 
10.03.17
01:34
пардон, соединение левое, конечно. иначе последние курсы потеряешь
9 Fram
 
10.03.17
01:39
эээ, еще подумал немного. надо еще раз обернуть в ВЫБРАТЬ и взять уже минимум по ПериодНач с группировкой по ПериодКон, Валюта, Курс
10 Fram
 
10.03.17
01:40
и в (7) МИНМИУМУМ, конечно, а не МАКСИМУМ
11 patria0muerte
 
10.03.17
02:03
12 patria0muerte
 
10.03.17
02:20
В твоем случае - примерно так:

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

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

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    МИНИМУМ(ВТКурсыСИнтегралом.НачалоПериода) КАК НачалоПериода,
    МАКСИМУМ(ВТКурсыСИнтегралом.КонецПериода) КАК КонецПериода,
    ВТКурсыСИнтегралом.Валюта,
    ВТКурсыСИнтегралом.Курс,
    ДОБАВИТЬКДАТЕ(ВТКурсыСИнтегралом.КонецПериода, ДЕНЬ, -ВТКурсыСИнтегралом.Интеграл) КАК Поле1
ИЗ
    ВТКурсыСИнтегралом КАК ВТКурсыСИнтегралом

СГРУППИРОВАТЬ ПО
    ДОБАВИТЬКДАТЕ(ВТКурсыСИнтегралом.КонецПериода, ДЕНЬ, -ВТКурсыСИнтегралом.Интеграл),
    ВТКурсыСИнтегралом.Валюта,
    ВТКурсыСИнтегралом.Курс

УПОРЯДОЧИТЬ ПО
    НачалоПериода
13 Экхонок
 
10.03.17
09:16
(12) Огромное спасибо! Тоже додумался группировать по дополнительному полю, но уже так устал, что не мог сообразить как это сделать. Ваш пример помог разобраться.
Спасибо всем!