Имя: Пароль:
1C
1С v8
Выбрать по две последние записи по всем измерениям РС запросом
,
0 Nikoss
 
16.05.13
14:22
Есть периодичный регистр:
Изм: Номенклатура
Рес: Количество

Допустим будут такие данные:
1.01 _ Ручка _ 14
1.01 _ Ручка _ 3
1.01 _ Карандаш _ 2
2.01 _ Ручка _ 7
2.01 _ Карандаш _ 3
3.01 _ Ручка _ 4
4.01 _ Ластик _ 1
4.01 _ Ручка _ 11
5.01 _ Ластик _ 2

Как выбрать по две записи каждой номенклатуры?
Т.е. чтобы было так:
3.01 _ Ручка _ 4
4.01 _ Ручка _ 11
1.01 _ Карандаш _ 2
2.01 _ Карандаш _ 3
4.01 _ Ластик _ 1
5.01 _ Ластик _ 2
1 LehhaK
 
16.05.13
14:23
А что не получается?
2 Nikoss
 
16.05.13
14:28
(1) ну я могу взять срез последних на дату, но этот же срез будет только по 1 штуке, как до второй добраться?
3 sda553
 
16.05.13
14:28
Идея такая (как выбрать вторые по истории), дальше сам думай:

Выбрать Период КАК НеМаксПериод, Измерение
Из
Регистр.МойРегистр Немаксимумы
ЛЕВОЕ СОЕДИНЕНИЕ
(
Выбрать Максимум(Период) КАК МаксПериод, Измерение
Из
Регистр.МойРегистр
СГРУППИРОВАТЬ ПО Измерение
) Максимумы По Максимумы.Период>Немаксимумы.Период И Максимумы.Измерение = НеМаксимумы.Измерение
4 LehhaK
 
16.05.13
14:29
Бери не срез. Бери весь регистр, сортируй по дате, выбирай первые 2. Должно прокатить ( я когда то давно на ценник выводил 2 цены, чтоб 1 зачеркивать, типа акция)
5 Sensodin
 
16.05.13
14:30
СрезПредпоследних
6 LehhaK
 
16.05.13
14:31
На вот:
ЗапросПредыдущаяЦена = Новый Запрос;
   ЗапросПредыдущаяЦена.Текст = "ВЫБРАТЬ ПЕРВЫЕ 2
                                |    ЦеныНоменклатуры.Цена,
                                |    ЦеныНоменклатуры.Период КАК Период
                                |ИЗ
                                |    РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
                                |ГДЕ
                                |    ЦеныНоменклатуры.Номенклатура = &Номенклатура
                                |    И ЦеныНоменклатуры.ТипЦен = &ТипЦен
                                |
                                |УПОРЯДОЧИТЬ ПО
                                |    Период УБЫВ";
   ЗапросПредыдущаяЦена.УстановитьПараметр("Номенклатура",СтрокаТаблицы.Номенклатура);
   ЗапросПредыдущаяЦена.УстановитьПараметр("ТипЦен",ТипЦен);
   РезультатЗапросаПредыдущаяЦена = ЗапросПредыдущаяЦена.Выполнить().Выгрузить();
7 sda553
 
16.05.13
14:38
(6) неправильно
8 LehhaK
 
16.05.13
14:40
(7) работает
9 samozvanec
 
16.05.13
14:41
(8) ты так всего 2 записи получишь. а надо в разрезе измерений
10 sda553
 
16.05.13
14:41
(8) Не сомневаюсь но выдает две строки, которые не имеют никакого отношения к тому, что нужно ТС
11 LehhaK
 
16.05.13
14:42
(9) он спросил, как получить 2 последние записи. я ответил. В разрезе измерений запилит поди сам
12 samozvanec
 
16.05.13
14:43
(11) ну да, там всего-то
|ГДЕ
|   ЛОЖЬ
дописать
13 sda553
 
16.05.13
14:43
(11) Не поверишь, но
1. "запиливание под разрез измерений" - это собственно самая главная задача,
2. Твой запрос не выбирает две последние записи в общем случае
14 Fragster
 
гуру
16.05.13
14:43
Что-то типа

Выбрать
*
Из регистр
где Регистр.Период, Регистратор в (Выбрать Первые 2 Период, Регистратор Из Регистр Как РегистрВложенный Где РеигстрВложенный.Измерения = Регистр.Измерения Упорядочить по РегистрВложенный.Период Убыв)
15 sda553
 
16.05.13
14:44
(14) Нет, то же неправильно.
16 Fragster
 
гуру
16.05.13
14:46
(15) почему?
17 LehhaK
 
16.05.13
14:46
(13) в (2) написано не так. Впрочем, у тебя полоска длиннее - ты советуй :)
18 sda553
 
16.05.13
14:47
(17) Я уже посоветовал в (3) - правда там с ошибками, лень исправлять, но набросок представление о решении дает
19 sda553
 
16.05.13
14:49
(16) Потому что в 1С нельзя из вложенных запросов обращаться к невложенным.
20 Fragster
 
гуру
16.05.13
14:50
(19) бугага!
21 ProgAL
 
16.05.13
14:53
ВЫБРАТЬ
   КурсыВалют.Валюта КАК Валюта,
   МАКСИМУМ(КурсыВалют.Период) КАК Период
ПОМЕСТИТЬ ВТПоследнихДат
ИЗ
   РегистрСведений.КурсыВалют КАК КурсыВалют
ГДЕ
   КурсыВалют.Период <= &Период

СГРУППИРОВАТЬ ПО
   КурсыВалют.Валюта

ИНДЕКСИРОВАТЬ ПО
   Валюта,
   Период
;

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

СГРУППИРОВАТЬ ПО
   КурсыВалют.Валюта

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

ВЫБРАТЬ
   ВТПоследнихДат.Валюта,
   ВТПоследнихДат.Период
ИЗ
   ВТПоследнихДат КАК ВТПоследнихДат

ИНДЕКСИРОВАТЬ ПО
   Валюта,
   Период
;

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

УПОРЯДОЧИТЬ ПО
   Валюта,
   Период
22 ProgAL
 
16.05.13
14:54
А дальше воспользоваться великой силой аналогии.
23 Fragster
 
гуру
16.05.13
14:57
вот это работает (самописька, для себя переписать несложно):


ВЫБРАТЬ
   ЦеныНоменклатуры.Период КАК Период,
   ЦеныНоменклатуры.Регистратор,
   ЦеныНоменклатуры.НомерСтроки,
   ЦеныНоменклатуры.Активность,
   ЦеныНоменклатуры.Номенклатура КАК Номенклатура,
   ЦеныНоменклатуры.ТипЦен КАК ТипЦен,
   ЦеныНоменклатуры.Качество КАК Качество,
   ЦеныНоменклатуры.Цена,
   ЦеныНоменклатуры.Валюта,
   ЦеныНоменклатуры.ЕдиницаИзмерения,
   ЦеныНоменклатуры.ЦенаВключаетНДС
ИЗ
   РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ГДЕ
   ЦеныНоменклатуры.Период В
           (ВЫБРАТЬ ПЕРВЫЕ 2
               РегистрВложенный.Период
           ИЗ
               РегистрСведений.ЦеныНоменклатуры КАК РегистрВложенный
           ГДЕ
               РегистрВложенный.Номенклатура = ЦеныНоменклатуры.Номенклатура
               И РегистрВложенный.ТипЦен = ЦеныНоменклатуры.ТипЦен
               И РегистрВложенный.Качество = ЦеныНоменклатуры.Качество
           УПОРЯДОЧИТЬ ПО
               РегистрВложенный.Период УБЫВ)

УПОРЯДОЧИТЬ ПО
   Номенклатура,
   ТипЦен,
   Качество,
   Период
24 Fragster
 
гуру
16.05.13
14:59
(21) а теперь 3 последних :)
25 Fragster
 
гуру
16.05.13
14:59
(24)+ или 5...
26 ProgAL
 
16.05.13
15:01
(24) Ваше решение короче. Но кореллированный запрос имеет спорное быстродействие.
27 samozvanec
 
16.05.13
15:03
(23) а если не на всю номенклатуру одновременно цены выставляют? если по разным позициям последние 2 периода не будут совпадать?
28 Fragster
 
гуру
16.05.13
15:04
(26) при соединении по всем измерениям - относительно неплохо. у меня запрос (23) отрабатывает за пол секунды, при этом возвращает 22 тысячи строк
29 Fragster
 
гуру
16.05.13
15:04
(27) все правильно будет
30 samozvanec
 
16.05.13
15:08
31 samozvanec
 
16.05.13
15:11
(21) и у тебя тоже самое. 2 периода максимальных выбрал, но не факт, что именно эти периоды максимальные у всех записей. в случае с валютами, конечно, все здорово, но не с установкой цен.
32 Fragster
 
гуру
16.05.13
15:19
(30) вариант (23) работает, инфа 100%
33 ProgAL
 
16.05.13
15:20
(31) Как это у всех записей? Там на каждую валюту опредяются свои 2 последние записи. Вы скачайте консоль запросов "Запросник" и посмотрите все ВТ. Или по частям разберите каждый запрос пакета в отдельном окне.
34 ProgAL
 
16.05.13
15:21
И в (23) основная таблица сканируется один раз, на каждую строку исходной таблицы выполняется определение двух последних дат, и если дата из основной таблицы входит в этот список, тогда ГДЕ ее не отсекает.
35 samozvanec
 
16.05.13
15:25
(33) максимум выдаст по столбцу
36 Fragster
 
гуру
16.05.13
15:26
(34) план запроса (23):

http://wstaw.org/m/2013/05/16/0.png
37 mikecool
 
16.05.13
15:27
выбрать измерения, максимум(период)
поместить ВТ

выбрать из ВТ
объединить
выбрать измерения, максимум(период)
внешнее соединение с ВТ ...
по измерения И период < ВТ.Период

мож так?
38 samozvanec
 
16.05.13
15:27
(34) таблица

25.06.13  Товар1
24.06.13  Товар1
24.06.13  Товар2
23.06.13  Товар2

ну и как ты думаешь, какие 2 даты тебе даст вложенный запрос из (23)?
39 Fragster
 
гуру
16.05.13
15:31
(38) вот универсальный запрос:
ВЫБРАТЬ
   1 КАК Период,
   "А" КАК Товар
ПОМЕСТИТЬ Данные

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

ВЫБРАТЬ
   2,
   "А"

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

ВЫБРАТЬ
   3,
   "А"

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

ВЫБРАТЬ
   2,
   "Б"

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

ВЫБРАТЬ
   3,
   "Б"

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

ВЫБРАТЬ
   4,
   "Б"
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Данные.Период,
   Данные.Товар
ИЗ
   Данные КАК Данные
ГДЕ
   Данные.Период В
           (ВЫБРАТЬ ПЕРВЫЕ 2
               Вложенный.Период
           ИЗ
               Данные КАК Вложенный
           ГДЕ
               Вложенный.Товар = Данные.Товар
           УПОРЯДОЧИТЬ ПО
               Вложенный.Период УБЫВ)
40 MaxS
 
16.05.13
15:37
Как вариант.
Если не требуется получить это в запросе, можно выбрать по всему регистру, отсортировать по дате, итоги по измерениям и по дате,  в цикле счетчик - досчитали до двух, команда "Продолжить" и переходим к следующему изменению...
41 ProgAL
 
16.05.13
15:37
(39) Единственный минус из (23) нужно дату отчески надожить во вложенный запрос.
42 ProgAL
 
16.05.13
15:39
(35) Максимум по столбцу, но по каждой валюте свой максимум.
43 PiterPrg
 
16.05.13
15:39
Я предлагаю как-то так:

ВЫБРАТЬ
   Товар,
   МАКСИМУМ(Период) КАК Период
ПОМЕСТИТЬ Периоды1
ИЗ
   РегистрСведений.РС КАК П1
СГРУППИРОВАТЬ ПО
   Товар;

ВЫБРАТЬ
   П2.Товар,
   МАКСИМУМ(П2.Период) КАК Период
ПОМЕСТИТЬ Периоды2
ИЗ
   РегистрСведений.РС КАК П2
ЛЕВОЕ СОЕДИНЕНИЕ
   Периоды1 КАК П1
ПО
   П1.Товар = П2.Товар И П2.Период < П1.Период
ГДЕ
   П1.Товар ЕСТЬ НЕ NULL    
СГРУППИРОВАТЬ ПО
   П2.Товар;

ВЫБРАТЬ
   Д.Товар,
   Д.КолВо
ИЗ
   РегистрСведений.РС КАК Д
ЛЕВОЕ СОЕДИНЕНИЕ
   Периоды1 КАК П1
ПО
   Д.Товар = П1.Товар И Д.Период = П1.Период
ЛЕВОЕ СОЕДИНЕНИЕ
   Периоды2 КАК П2
ПО
   Д.Товар = П2.Товар И Д.Период = П2.Период
ГДЕ
   П1.Товар ЕСТЬ НЕ NULL И П2.Товар ЕСТЬ НЕ NULL
44 PiterPrg
 
16.05.13
15:41
(43) Что-то последняя строчка в код не включилась :-) Ну я думаю, понятно
45 samozvanec
 
16.05.13
15:42
(42) ага, а выдаст по столбцу, я о том же
46 PiterPrg
 
16.05.13
15:46
(43) В последнем условии должно быть или :-)

 П1.Товар ЕСТЬ НЕ NULL ИЛИ П2.Товар ЕСТЬ НЕ NULL

Вот так
47 samozvanec
 
16.05.13
15:59
ВЫБРАТЬ
   КурсыВалютСрезПоследних.Период,
   КурсыВалютСрезПоследних.Валюта
ПОМЕСТИТЬ йцу
ИЗ
   РегистрСведений.КурсыВалют.СрезПоследних КАК КурсыВалютСрезПоследних
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   КурсыВалютСрезПоследних.Период,
   КурсыВалютСрезПоследних.Валюта
ПОМЕСТИТЬ фыв
ИЗ
   РегистрСведений.КурсыВалют.СрезПоследних(
           ,
           НЕ (Период, Валюта) В
                   (ВЫБРАТЬ
                       й.Период,
                       й.Валюта
                   ИЗ
                       йцу КАК й)) КАК КурсыВалютСрезПоследних
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   йцу.Период,
   йцу.Валюта
ИЗ
   йцу КАК йцу

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

ВЫБРАТЬ
   фыв.Период,
   фыв.Валюта
ИЗ
   фыв КАК фыв
48 ProgAL
 
16.05.13
16:11
Жесть, но сработет.
49 samozvanec
 
16.05.13
16:12
про максимум я нагло солгал) извиняюсь
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн