Вход | Регистрация
 
1С:Предприятие :: 1С:Предприятие 8 общая

Возможно ли такое выбрать запросом?

Возможно ли такое выбрать запросом?
Я
   Kozitsyn
 
23.11.20 - 16:46
Приветствую, коллеги! )

Cкрин обычного периодического рег. сведений с одним измерением - https://yadi.sk/i/Qqv4qRyGDIQwfg

Необходимо в рамках запроса выбрать только начальные даты по всем подряд записанным физ.лицам, чтобы получилось вот так:
03.11.2020 | Бельдыев
09.11.2020 | Лоханкина
22.11.2020 | Бельдыев

Группировку и минимум по дате, а также срезы  не предлагать, тогда мы потерям второго Бельдыева :)

Возможно ли такое сделать в рамках запроса?
   acht
 
1 - 23.11.20 - 16:48
выбрать минимум(период), физик сгрупировать по физик
   acht
 
2 - 23.11.20 - 16:49
Иначе твое 

03.11.2020 | Бельдыев
09.11.2020 | Лоханкина
22.11.2020 | Бельдыев

Противоричит постановке.
   Kozitsyn
 
3 - 23.11.20 - 16:50
(1) тогда мы потерям второго Бельдыева 
(2) не противоречит - "по всем ПОДРЯД записанным физ.лицам"
   БаксПо90
 
4 - 23.11.20 - 16:50
Т.е. вторую лоханкину можно потерять а бельдыева нельзя ..
   Малыш Джон
 
5 - 23.11.20 - 16:50
(0) можно, но непроизводительно
   Cthulhu
 
6 - 23.11.20 - 16:51
различные
   Kozitsyn
 
7 - 23.11.20 - 16:51
(4) вторая Лоханкина идет ПОДРЯД, ее как раз не нужно выводить, а вот второй Бельдыев записан уже после Лозанкиной и его нужно оставить - только первую дату
   Kozitsyn
 
8 - 23.11.20 - 16:53
(6) что "различные" ? тогда опять же второго Быльдыева грохнем, а он нужен
   PuhUfa
 
9 - 23.11.20 - 16:54
(7) а в чем тайный смысл сего действия? мне чисто для себя...
   Kozitsyn
 
10 - 23.11.20 - 16:55
(9) в рег. сведений записывается периодически определённые статусы (я сильно упростил задачу) и они могут много раз повторяться одни и те же подряд, вот от этого "подряд" нужно избавиться. понятное дело, что тут проще переделать регистр, чтобы в него вприципе не записывались подряд одни и теже данные, но пока вопрос в другом
   RomanYS
 
11 - 23.11.20 - 16:55
(0) так одно измерение или ресурс?
   Kozitsyn
 
12 - 23.11.20 - 16:56
(11) Измерение - физ. лицо
   RomanYS
 
13 - 23.11.20 - 16:57
(0)
Засунуть в ВТ,
пронумеровать записи,
соединить записи со следующей по номеру,
отфильтровать лишние (повторяющиеся) записи
   Малыш Джон
 
14 - 23.11.20 - 16:58
(13) нумеровать лишнее
   Cthulhu
 
15 - 23.11.20 - 16:58
»
   Kozitsyn
 
16 - 23.11.20 - 16:59
(13) а если ПОДРЯД таких строк будут сотни (с одним физиком и разыми датами), прокатит этот вариант?
   RomanYS
 
17 - 23.11.20 - 16:59
+(13)  без нумерации придётся группировать с минимум(Рег2.Период)  и ещё односоединение
   RomanYS
 
18 - 23.11.20 - 17:00
(16) А в чем проблема? Совпало с предыдущим - запись не берёшь
   RomanYS
 
19 - 23.11.20 - 17:01
(12) странная структура, тогда могут быть разные записи на одну дату - что с ними делать?
   Kozitsyn
 
20 - 23.11.20 - 17:01
(15) идиот здесь не я, если вы такое предлагаете. В итоге вы получите исходную таблицу, потому что даты и так различные
   Kozitsyn
 
21 - 23.11.20 - 17:06
(19) пока представим что такого нет. Пока задача понять - в принципе возможно ли вынуть запросом только начальные записи по всем подряд записанным физикам.
   RomanYS
 
22 - 23.11.20 - 17:07
(21) В принципе возможно
   ам794123
 
23 - 23.11.20 - 17:08
(13) поддерживаю, давно хотел найти применение функция языка запросов АВТОНОМЕРЗАПИСИ().
   RomanYS
 
24 - 23.11.20 - 17:09
(23) есть такое)))
   Kozitsyn
 
25 - 23.11.20 - 17:11
(13) Благодарю. Попробую. Отпишусь
   Kozitsyn
 
26 - 23.11.20 - 17:29
ВЫБРАТЬ
    МойРегистр.ФизЛицо КАК ФизЛицо,
    МойРегистр.Период КАК Период,
    АВТОНОМЕРЗАПИСИ() КАК НомерСтроки
ПОМЕСТИТЬ ВТ
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр
;

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

ВЫБРАТЬ
    МойРегистр.ФизЛицо КАК ФизЛицо,
    МойРегистр.Период КАК Период,
    АВТОНОМЕРЗАПИСИ() КАК НомерСтроки
ПОМЕСТИТЬ ВТ2
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр
;

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

ВЫБРАТЬ
    ВТ.ФизЛицо КАК ФизЛицо,
    ВТ.Период КАК Период
    ИЗ
    ВТ КАК ВТ
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ2 КАК ВТ2
        ПО (ВТ.НомерСтроки = ВТ2.НомерСтроки + 1)
ГДЕ
    ЕСТЬNULL(ВТ2.ФизЛицо, "") <> ВТ.ФизЛицо
   Kozitsyn
 
27 - 23.11.20 - 17:31
(26) Получился такой запрос. Он работает. Но, если я например добавлю еще одну Лоханкину на 21.11.2020, и он почему её еще выводит, хотя не должен, потому что она относится к той Лоханкиной. Видимо еще нужно сортировать записи перед сравнением
   Kozitsyn
 
28 - 23.11.20 - 17:34
Добавил ИНДЕКСИРОВАТЬ ПО Период, в итоге вроде всё заработало, всем спасибо, вот итоговый запрос:

ВЫБРАТЬ
    МойРегистр.ФизЛицо КАК ФизЛицо,
    МойРегистр.Период КАК Период,
    АВТОНОМЕРЗАПИСИ() КАК НомерСтроки
ПОМЕСТИТЬ ВТ
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр

ИНДЕКСИРОВАТЬ ПО
    Период
;

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

ВЫБРАТЬ
    МойРегистр.ФизЛицо КАК ФизЛицо,
    МойРегистр.Период КАК Период,
    АВТОНОМЕРЗАПИСИ() КАК НомерСтроки
ПОМЕСТИТЬ ВТ2
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр

ИНДЕКСИРОВАТЬ ПО
    Период
;

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

ВЫБРАТЬ
    ВТ.ФизЛицо КАК ФизЛицо,
    ВТ.Период КАК Период
ИЗ
    ВТ КАК ВТ
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ2 КАК ВТ2
        ПО (ВТ.НомерСтроки = ВТ2.НомерСтроки + 1)
ГДЕ
    ЕСТЬNULL(ВТ2.ФизЛицо, "") <> ВТ.ФизЛицо
   RomanYS
 
29 - 23.11.20 - 17:42
(26) (28) Достаточно одной ВТ, в полсднем запросе будет
ИЗ
    ВТ КАК ВТ
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ2
        ПО (ВТ.НомерСтроки = ВТ2.НомерСтроки + 1)
   RomanYS
 
30 - 23.11.20 - 17:44
Блин, а к АВТОНОМЕРЗАПИСИ порядок указать нельзя? Без этого как бы смыла нет, номера нужны именно в порядке дат
 
 Рекламное место пустует
   Kozitsyn
 
31 - 23.11.20 - 17:46
(29) Да, так будет проще )

ВЫБРАТЬ
    МойРегистр.ФизЛицо КАК ФизЛицо,
    МойРегистр.Период КАК Период,
    АВТОНОМЕРЗАПИСИ() КАК НомерСтроки
ПОМЕСТИТЬ ВТ
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр

ИНДЕКСИРОВАТЬ ПО
    Период
;

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

ВЫБРАТЬ
    ВТ.ФизЛицо КАК ФизЛицо,
    ВТ.Период КАК Период
ИЗ
    ВТ КАК ВТ
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ2
        ПО (ВТ.НомерСтроки = ВТ2.НомерСтроки + 1)
ГДЕ
    ЕСТЬNULL(ВТ2.ФизЛицо, "") <> ВТ.ФизЛицо
   Kozitsyn
 
32 - 23.11.20 - 17:46
(30) порядок я решил с помощью индексирования
   Kozitsyn
 
33 - 23.11.20 - 17:48
Без индексирования всё разъезжается )
   RomanYS
 
34 - 23.11.20 - 17:48
(32) А это чем-то подтверждается, или ты просто решил, что решил :)?
   Kozitsyn
 
35 - 23.11.20 - 17:50
(34) Подтверждается результатами тестирования. Без индексирования, если добавить еще одну строку к подряд записанным данными, то это последнее добавление в результате запроса отобразится последней строкой, а если проидексировать, то все будет хорошо, не отобразится )
   acht
 
36 - 23.11.20 - 18:05
(27) Если упороться, то можно написать на 1С коррелирующий подзапрос

ВЫБРАТЬ
  ДАТАВРЕМЯ(2020, 11, 3) КАК Период,
  "Бельдыев" КАК Физик
ПОМЕСТИТЬ
  Регистр
ОБЪЕДИНИТЬ ВЫБРАТЬ ДАТАВРЕМЯ(2020, 11, 5),  "Бельдыев"
ОБЪЕДИНИТЬ ВЫБРАТЬ ДАТАВРЕМЯ(2020, 11, 9),  "Лоханкина"
ОБЪЕДИНИТЬ ВЫБРАТЬ ДАТАВРЕМЯ(2020, 11, 10), "Лоханкина"
ОБЪЕДИНИТЬ ВЫБРАТЬ ДАТАВРЕМЯ(2020, 11, 22), "Бельдыев"
ОБЪЕДИНИТЬ ВЫБРАТЬ ДАТАВРЕМЯ(2020, 11, 24), "Бельдыев"
;

ВЫБРАТЬ
  Текущий.Период,
  Текущий.Физик
ИЗ
  Регистр КАК Текущий
ЛЕВОЕ СОЕДИНЕНИЕ    
  Регистр КАК Предыдущий
ПО  
  Предыдущий.Период В (
    ВЫБРАТЬ 
      МАКСИМУМ(РегистрВнутр.Период)
    ИЗ          
      Регистр КАК РегистрВнутр
    ГДЕ         
      РегистрВнутр.Период < Текущий.Период
  )
ГДЕ 
      Предыдущий.Физик ЕСТЬ NULL
  ИЛИ Предыдущий.Физик <> Текущий.Физик
УПОРЯДОЧИТЬ ПО 
  Текущий.Период
   RomanYS
 
37 - 23.11.20 - 18:13
(36) страшно :) А если дат будет хотя бы 1000?

И МАКСИМУМ(РегистрВнутр.Период) здесь наверное лучше на "первые 1" заменить
   acht
 
38 - 23.11.20 - 18:17
(37) Не, на первые 1 оно тебя пошлет в части "упорядочить по"

Производительтность, кнечн, мерять надо. Думаю, что на с индексом по периоду будет не так страшно. Но на план запроса посмотреть эт уже завтра...
   RomanYS
 
39 - 23.11.20 - 18:19
(38) конечно с "упорядочить по". По идее побыстрее должно быть чем максимум
   acht
 
40 - 23.11.20 - 18:20
(39) Зависит от. На MSSQL, ЕМНИП, еквифаллентно
   acht
 
41 - 23.11.20 - 18:22
(39) а с "упорядочить по" в подзапросе тебя пошлет 1С, которая не будет такое компилировать
   RomanYS
 
42 - 23.11.20 - 18:24
(41) проверил, не послала. База файловая.

ВЫБРАТЬ
    Текущий.Период,
    Текущий.Физик
ИЗ
    Регистр КАК Текущий
        ЛЕВОЕ СОЕДИНЕНИЕ Регистр КАК Предыдущий
        ПО (Предыдущий.Период В
                (ВЫБРАТЬ ПЕРВЫЕ 1
                    РегистрВнутр.Период
                ИЗ
                    Регистр КАК РегистрВнутр
                ГДЕ
                    РегистрВнутр.Период < Текущий.Период
                УПОРЯДОЧИТЬ ПО
                    РегистрВнутр.Период УБЫВ))
ГДЕ
    (Предыдущий.Физик ЕСТЬ NULL
            ИЛИ Предыдущий.Физик <> Текущий.Физик)

УПОРЯДОЧИТЬ ПО
    Текущий.Период
   RomanYS
 
43 - 23.11.20 - 18:29
(38) В любом случае слишком страшно для продуктива. Безопасная альтернатива (13) в (17).

Соединять сразу три таблицы по общему условию (а по сути КорЗ - это ещё одно соединение) - слишком рискованно. Лучше по шагам, сначала Максимум, а потом ещё одно соединение
   МимохожийОднако
 
44 - 23.11.20 - 18:32
Срез первых записей не подходит?
   RomanYS
 
45 - 23.11.20 - 18:34
(44) Не, физлицо - измерение, и ему не срез нужен совсем. Скорее периоды действия
   Alres
 
46 - 23.11.20 - 18:43
ВЫБРАТЬ
    МойРегистр.Период КАК Период,
    МойРегистр.ФИО КАК ФИО
ПОМЕСТИТЬ МойРегистр
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр

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

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

ВЫБРАТЬ
    МойРегистр.Период КАК Период,
    МойРегистр.ФИО КАК ФИО,
    МИНИМУМ(ЕСТЬNULL(МойРегистр_КонецПериода.Период, ДАТАВРЕМЯ(2099, 11, 1))) КАК КонецПериода
ПОМЕСТИТЬ МойРегистр_КонецПериода
ИЗ
    МойРегистр КАК МойРегистр
        ЛЕВОЕ СОЕДИНЕНИЕ МойРегистр КАК МойРегистр_КонецПериода
        ПО (МойРегистр.Период < МойРегистр_КонецПериода.Период)
            И (МойРегистр.ФИО <> МойРегистр_КонецПериода.ФИО)

СГРУППИРОВАТЬ ПО
    МойРегистр.Период,
    МойРегистр.ФИО
;

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

ВЫБРАТЬ
    МИНИМУМ(МойРегистр_КонецПериода.Период) КАК Период,
    МойРегистр_КонецПериода.ФИО КАК ФИО,
    МойРегистр_КонецПериода.КонецПериода КАК КонецПериода
ИЗ
    МойРегистр_КонецПериода КАК МойРегистр_КонецПериода

СГРУППИРОВАТЬ ПО
    МойРегистр_КонецПериода.ФИО,
    МойРегистр_КонецПериода.КонецПериода
   RomanYS
 
47 - 23.11.20 - 18:47
(46) Идея верная.
Только зачем  И (МойРегистр.ФИО <> МойРегистр_КонецПериода.ФИО) во втором запросе? Лишние записи получишь, условие в 3-м запросе должно быть
   Alres
 
48 - 23.11.20 - 19:14
(47) Чтобы получить дату изменения физлица, она будет одинаковая для 03 Бельдыев и 05 Бельдыев чтобы по ней потом можно было свернуть и оставить только 03 Бельдыев
   RomanYS
 
49 - 23.11.20 - 19:16
(48) У тебя левое соединение и нет условия ГДЕ, значит ты получишь ВСЕ записи из левой таблицы.
   RomanYS
 
50 - 23.11.20 - 19:20
(48) Ок. Сгруппировать возможно я не учёл. Возможно правильно (проверять лень), но я бы сделал по другому :)
   Alres
 
51 - 23.11.20 - 19:25
(50)
Я бы убрал возможность повторной записи одного физлица и вопрос снят :)
   Kozitsyn
 
52 - 23.11.20 - 19:31
Проверил этот запрос тоже работает. Во как, думал никак не получится сделать, а тут даже несколько рабочих вариантов есть )))) Спасибо вам, неравнодушные люди ;)


ВЫБРАТЬ
    МойРегистр.Период КАК Период,
    МойРегистр.ФизЛицо КАК Физик
ПОМЕСТИТЬ Текущий
ИЗ
    РегистрСведений.МойРегистр КАК МойРегистр
;

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

ВЫБРАТЬ
    Текущий.Период КАК Период,
    Текущий.Физик КАК Физик
ИЗ
    Текущий КАК Текущий
        ЛЕВОЕ СОЕДИНЕНИЕ Текущий КАК Предыдущий
        ПО (Предыдущий.Период В
                (ВЫБРАТЬ ПЕРВЫЕ 1
                    РегистрВнутр.Период КАК Период
                ИЗ
                    РегистрСведений.МойРегистр КАК РегистрВнутр
                ГДЕ
                    РегистрВнутр.Период < Текущий.Период
                УПОРЯДОЧИТЬ ПО
                    Период УБЫВ))
ГДЕ
    (Предыдущий.Физик ЕСТЬ NULL
            ИЛИ Предыдущий.Физик <> Текущий.Физик)

УПОРЯДОЧИТЬ ПО
    Текущий.Период
   Kozitsyn
 
53 - 23.11.20 - 19:39
Хотя в (31) более правильный код, потому что, если в (52) вклинить в подряд записанные данные по физику другого физика, то всё рушится. А (52) правильно отрабатывает, он как разрывает период, а потом его возобновляет.
   RomanYS
 
54 - 23.11.20 - 20:03
(52) слишком рискованно - можно подвесить сервак, если данных немного прибавится (но это не точно).
По (31) я не понимаю, как гарантируется упорядоченность по периоду.
   acht
 
55 - 23.11.20 - 23:24
(54) >  я не понимаю, как гарантируется упорядоченность по периоду.

Созданный индекс по периоду на времянку, он по умолчанию как ASC делается =)
А дальше ему тупо везет, что чтение строк в порядке кластерного индекса идет, а АВТОНОМЕРЗАПИСИ() дает identity с шагом 1

Профайлер я еще не запускал, так что могу врать.
   RomanYS
 
56 - 23.11.20 - 23:31
(55) Получается АВТОНОМЕРЗАПИСИ как чемодан без ручки, потенциально офигенная штука, которой кучу задач можно решать, при этом без банального упорядочить - результат непредсказуем.
Но в большинстве случаев вам буде вести... т.е. ещё и мина замедленного действия
   Cthulhu
 
57 - 24.11.20 - 01:24
(56): почему без упорядочить?
   МимохожийОднако
 
58 - 24.11.20 - 07:09
(51) Присоединяюсь. При изменении кода, который не позволяет записывать в новой дате того же сотрудника, даст готовую таблицу из записей основной таблицы регистра. Или вместо запроса тупой перебор вниз по датам.
   dmpl
 
59 - 24.11.20 - 07:53
(35) И чо? Раньше, например, вызов Документ.Записать() перепроводил документ при записи, если он был проведен. А с определенной версии платформы только записывает.
   Ненавижу 1С
 
60 - 24.11.20 - 08:43
как учитывать факт записи нескольких физлиц одной датой?
 
 Рекламное место пустует
   Said_We
 
61 - 24.11.20 - 13:11
(56) Да это так.

Я не помню, что бы можно было использовать как-то иначе чем так:
SELECT row_number() over(ORDER BY <Поле1 [,Поле2...ПолеN]>) as NPP

Плюс там ещё может быть "partition BY", но не важно...

У 1С свое видение.... Как всегда.
Всандалили автоупорядочивание только во внутренние таблицы, в которых нет сортировки без ограничения TOP.
Так что в общем случае "АВТОНОМЕРЗАПИСИ" использовать нельзя пока нигде.

Так что пока только "коррелирующий подзапрос". Только необходимо, четко отделять записи друг от друга.
   RomanYS
 
62 - 24.11.20 - 13:25
(61) А если взять "Первые 999999999999" и упорядочить, сработает?
   Said_We
 
63 - 24.11.20 - 13:31
Да, но если будет больше, то....
   Said_We
 
64 - 24.11.20 - 13:36
(62) Только по моему девяток слишком много. Там ограничение есть.
   RomanYS
 
65 - 24.11.20 - 13:39
(63)(64) Ну уже что-то, лайфхак так сказать)
   Said_We
 
66 - 24.11.20 - 13:51
Если бы синтаксис был бы какой-то такой, то было бы здорово:

АВТОНОМЕРЗАПИСИ НАД (ГРУППИРОВАТЬ ПО <Поле1 [,Поле2...,ПолеN]> СОРТИРОВАТЬ ПО <Поле1 [,Поле2...,ПолеN]>)

или

АВТОНОМЕРЗАПИСИ НАД (СГРУППИРОВАТЬ ПО <Поле1 [,Поле2...,ПолеN]> УПОРЯДОЧИТЬ ПО <Поле1 [,Поле2...,ПолеN]>)

Тем более, что на T-SQL такое переводится практически 1 к 1.
   Said_We
 
67 - 24.11.20 - 13:57
А потом туда же прикрутить:
MAХ(<ИмяПоля>) НАД (РАЗБИЕНИЕ НА <Поле1 [,Поле2...,ПолеN]>)
Тоже переводится 1 к 1

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


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.