Имя: Пароль:
1C
1C 7.7
v7: Запрос на Sqlite
0 Sam1C
 
16.02.18
12:23
доброго дня! может кто подскажет идейку как выбрать для справочника контрагента последний документ определенного вида. Пока только в голову лезут выборка всех контрагентов и потом подзапросами по каждому выбирать Последний док. Но 10000 контрагентов 10000 подзапросов, что-то ни оптимально
1 Ёпрст
 
16.02.18
12:27
(0)
обычный коррелированный подзапрос в селекте
2 Ёпрст
 
16.02.18
12:29
ну или селект клиентос из справочника + лефт джоин (селект клиентос фром документ + гроуп бай  клиентосу и максимум дата и всё
3 Sam1C
 
16.02.18
13:15
(2)

SELECT Контрагенты.ID [Ссылка :Справочник.Контрагенты]
    , Контрагенты.Менеджер [Менеджер :Справочник.Менеджеры]
    , срм_Событие.IDDOC [срм_СобытиеСсылка :Документ.срм_Событие]
    , Max(Журнал.DATE) МаксимумДокумент_дата
FROM [Справочник.Контрагенты] AS Контрагенты
    LEFT OUTER JOIN [Документ.срм_Событие] AS срм_Событие  ON Контрагенты.ID = срм_Событие.шКонтрагент
    LEFT OUTER JOIN [_1S.JOURN] AS Журнал ON срм_Событие.IDDOC = Журнал.IDDOC
GROUP BY Контрагенты.ID
    , Контрагенты.Менеджер
    , срм_Событие.IDDOC
4 Sam1C
 
16.02.18
13:18
(3) Что я делаю ни так? выдает все документы по каждому контрагенту, а не последний
5 alxxsssar
 
16.02.18
13:22
(4) Группировки у тебя не излишние? По Менеджеру и Событию (Тем более я так понимаю это документ) зачем группировать?
6 Sam1C
 
16.02.18
13:27
(5) согласен, щас оставлю только по Контрагенту по пробую
7 alxxsssar
 
16.02.18
13:29
(6) из итоговых полей не забудь удалить, а то ошибка будет
8 Sam1C
 
16.02.18
13:33
(7) какие итоговых?, я удаляю только из GROUP BY. Мне же в ТЗ нужна ссылка на документ, а не только его дата:
SELECT Контрагенты.ID [Ссылка :Справочник.Контрагенты]
    , Контрагенты.Менеджер [Менеджер :Справочник.Менеджеры]
    , срм_Событие.IDDOC [срм_СобытиеСсылка :Документ.срм_Событие]
    , Max(Журнал.DATE) МаксимумДокумент_дата
FROM [Справочник.Контрагенты] AS Контрагенты
    LEFT OUTER JOIN [Документ.срм_Событие] AS срм_Событие  ON Контрагенты.ID = срм_Событие.шКонтрагент
    LEFT OUTER JOIN [_1S.JOURN] AS Журнал ON срм_Событие.IDDOC = Журнал.IDDOC
GROUP BY Контрагенты.ID
9 alxxsssar
 
16.02.18
13:36
менеджера и событие. Иначе запрос ошибку выдаст, что они не участвуют в group by
10 Sam1C
 
16.02.18
13:39
(9) не, тут пракатывает. в групп не обязательно все поля указывать которые есть в выборке. Короче запрос в (8) отработал на ура, данные верные, но 10 минут, это конечно не серьезно
11 alxxsssar
 
16.02.18
13:53
(10) поздравляю
12 Sam1C
 
16.02.18
14:25
(11) поздравлять не с чем. очень долго работает
13 Darych
 
16.02.18
14:33
(12) парси словарь, через ado к таблице дока скулевый запрос
14 Ёпрст
 
16.02.18
15:31
Тебе нужно найти max(idx_IDDOCDEF_DATE_TIME_IDDOC) и по этому полю отфильтровать
15 alxxsssar
 
16.02.18
15:41
(12) а сколько объектов в базе у тебя?
16 alxxsssar
 
16.02.18
15:43
(15) и может сделать сперва выборку документов, проиндексировать ее и джойнить контрагентов с этой таблицей по индексам?
17 Ёпрст
 
16.02.18
15:50
На вот, занимайся


select
    Спр.id [Клиентос:Справочник.Контрагенты]
   ,right(Таб.МаксПозиция,9)  [Док:Документ.срм_Событие]
from [Справочник.Контрагенты] Спр
left join(
select
    Док.Контрагент,
    max(idx_IDDOCDEF_DATE_TIME_IDDOC) МаксПозиция
from Журнал Жур
inner join [Документ.срм_Событие] Документ
group by Док.Контрагент) Таб on Таб.Контрагент=Спр.id
18 Sam1C
 
16.02.18
16:17
(15) да не много 10000 контрагентов 50000 документов этого вида
19 alxxsssar
 
16.02.18
16:25
(18) тогда даже для (8) это слишком долго. У меня 3 миллиона записей выбираются за 2,5 минуты
20 alxxsssar
 
16.02.18
16:26
+(19) тоже с пересчетами и джойнами конечно
21 Djelf
 
16.02.18
19:21
Отборы в журнале есть? Если есть по нужным критериям - можно использовать, должно ускорить.
> Но 10000 контрагентов 10000 подзапросов, что-то ни оптимально
Можно развернуть логику в обратную сторону - первым в запросе выбирать самую тяжелую таблицу и применить к ней все возможные условия, это видимо Журнал и джойнить к нему, а не наоборот.
100500 подзапросов к тяжелой таблице и убивают скорость.
22 Злопчинский
 
16.02.18
20:23
Интересно за сколько 17 отработает
23 Djelf
 
17.02.18
12:03
(22) Смотря на какой версии sqlite.
Оригинальная 1.0.2.6 на движке 3.7.10 будет выполнять запрос
SELECT
max(Журнал.idx_IDDOCDEF_DATE_TIME_IDDOC)
,Журнал.IDDOC
FROM  [_1S.JOURN] AS Журнал

за ~3с на 1.5м записей, умножаем на 10000 и плачем.
А вот начиная с движка 3.7.16 этот запрос выполниться всего за 1мс т.к. движок начал понимать что если индекс упорядочен, то просматривать всю таблицу не имеет смысла.
24 Djelf
 
17.02.18
13:56
(0) А это за сколько выполнится?

SELECT
    срм_Событие.Контрагент [Контрагент $Справочник.Контрагенты]
    ,Контрагент.Менеджер [Менеджер $Справочник.Менеджеры]
    ,Журнал.IDDOC [Документ $Документ.Реализация]
FROM [_1S.JOURN] AS Журнал
INNER JOIN [Документ.срм_Событие] AS срм_Событие ON срм_Событие.IDDOC=Журнал.IDDOC
INNER JOIN Справочник_Контрагенты AS Контрагент ON Контрагент.ID=срм_Событие.шКонтрагент
WHERE Журнал.IDDOCDEF=:ВидДокумента.срм_Событие
GROUP BY срм_Событие.шКонтрагент
HAVING max(Журнал.idx_DATE_TIME_IDDOC)

25 mistеr
 
17.02.18
14:44
Ограничить дату документов снизу неким разумным значением, например год. Выбрать все доки, сгруппировать по контрагенту, взять максимум.
26 Ёпрст
 
17.02.18
14:53
(24) этот запрос не вернёт всех клиентосов
27 Ёпрст
 
17.02.18
14:53
и это, нафига ты пишешь [_1S.JOURN] ...когда проще писать
Журнал ...
28 Ёпрст
 
17.02.18
14:53
?
29 Djelf
 
17.02.18
15:39
(28) Так было написано у автора топика в (3).
Я не стал менять ;)

(27) То правда! Тогда так:

SELECT
    Контрагент.ID [Контрагент $Справочник.Контрагенты]
    ,Контрагент.Менеджер [Менеджер $Справочник.Менеджеры]
    ,Выборка.IDDOC [Документ $Документ.срм_Событие]
FROM Справочник_Контрагенты AS Контрагент
LEFT JOIN
    (SELECT
        срм_Событие.Контрагент AS Контрагент
        ,срм_Событие.IDDOC AS IDDOC
    FROM Журнал
    LEFT JOIN Документ_срм_Событие AS срм_Событие ON срм_Событие.IDDOC=Журнал.IDDOC
    LEFT JOIN Справочник_Контрагенты AS Контрагент ON Контрагент.ID=срм_Событие.шКонтрагент
    WHERE Журнал.IDDOCDEF=:ВидДокумента.срм_Событие
    GROUP BY срм_Событие.Контрагент
    HAVING max(Журнал.idx_DATE_TIME_IDDOC)
) AS Выборка ON Выборка.Контрагент=Контрагент.ID
WHERE Контрагент.ISFOLDER=2
GROUP BY Контрагент.ID
30 Ёпрст
 
17.02.18
15:51
(29) последний group by лишний же
31 Djelf
 
17.02.18
15:59
(30) Да, перестраховался ;(
32 SleepyHead
 
гуру
17.02.18
18:08
Чем-то мне это все напоминает анекдот про Ржевского и господ офицеров, развлекавшихся с девушкой на бильярдном столе.

Господа, с вами все в порядке? Штатным языком 1с77 задача решается в три строки кода.
33 Злопчинский
 
17.02.18
19:22
(32) жжошь!
34 Djelf
 
17.02.18
19:24
Ну вот пришел SleepyHead и все испортил ;(
А столько еще идей было...
35 Злопчинский
 
17.02.18
19:32
СделатьВсе()
36 Ёпрст
 
18.02.18
19:38
(32) Ну напиши нам, эти строки,
так, на поржать
37 Aleksey
 
18.02.18
19:51
(36) НУ в типовых Контрагент - это графа отбора, а значит
ВыбратьПоЗначению + ОбратныйПорядок
Разве нет?
38 Ёпрст
 
18.02.18
19:57
(37) у него не типповая и нет графы отбора + нужен определенный вид дока
39 Ёпрст
 
18.02.18
19:58
+ нужны все клиентосы, а не только те, по которым были документы.
40 Ёпрст
 
18.02.18
19:58
И да.. графа отбора, ничего не даст, в типовом случае :)))
41 Ёпрст
 
18.02.18
20:03
разве что перебор справочника клиентосов и для каждого выбратьпозначению с условием на вид дока в перебое..
но, это не наш метод, слишком долго
42 Aleksey
 
18.02.18
20:21
Ну я так понимаю нужно просто в карточки клиента вывести список, чтобы как в 8-ке
43 Sam1C
 
18.02.18
20:24
(22) В (17) в подзапросе нет отбора по виду документа по этому он больше часа лопатит. И наверно нет функции right в SQlite вместо нее substr, substr (Таб.МаксПозиция,-9) походу делать так нужно.
44 Sam1C
 
18.02.18
20:27
Запрос в (8) работает 10 минут как говорилось выше, а вот (29) 18 секунд, спасибо  Djelf.
45 Sam1C
 
18.02.18
20:54
(29) Только не могу понять за чем во вложенном запросе идет соединение со справочником Контрагенты:
LEFT JOIN [Справочник.Контрагенты] AS Контрагент ON Контрагент.ID=срм_Событие.шКонтрагент.
Контрагента тянем то из документа для таблицы Выборка, зачем подключать еще справочник контрагентов
Или это опечатка?
46 Ёпрст
 
19.02.18
12:23
(43) есть там всё. Там иннер джоин
47 Ёпрст
 
19.02.18
12:24
Ну и (23) смотри - поставь другую версию 1sqlite
48 Ёпрст
 
19.02.18
12:24
(45) это лишнее
49 SleepyHead
 
гуру
19.02.18
12:27
(38) "Нет графы отбора"

Мыши плакали, кололись, но продолжали жрать кактус.
Господа, мне с вами не по пути ))
50 Ёпрст
 
19.02.18
12:40
(49) Покажи 3 строки с кодом, если есть графа отбора.
51 Djelf
 
19.02.18
13:11
(44) Если поставишь версию поновее будет ~8с
http://catalog.mista.ru/public/559826/
https://cloud.mail.ru/public/9znr/ZJ6ULE9aR
Но предупреждаю - некоторые запросы могут начать тормозить, особенно с использованием IN. Так что сначала на копии прогони.

(45) Не доводил до идеала. Все равно это видимо только часть запроса.
52 Sserj
 
19.02.18
13:55
хех, а еще с скулайтом можно извратиться :)

Запрос.ВыполнитьЗапрос("CREATE TEMP TABLE ПоследниеДокументы (Клиент varchar(9) PRIMARY KEY, Док varchar(9)));
Запрос.ВыполнитьЗапрос("
INSERT INTO ПоследниеДокумент (Клиент,Док)
SELECT
  пДокументы.Клиент
  , пДокументы.Док
FROM
  (SELECT
    срм_Событие.Контрагент as Клиент
    , Журнал.IDDOC as Док
    , Max(Журнал.idx_DATE_TIME_IDDOC)
  FROM
    Журнал Д
    JOIN Документ_срм_Событие AS срм_Событие
    ON срм_Событие.IDDOC=Журнал.IDDOC
  GROUP BY
    срм_Событие.Контрагент
  ) as пДокументы
");
Запрос.ВыполнитьЗапрос("
SELECT
  Спр.ID as [Клиент :Справочник.Контрагенты]
  , пДокументы.Док as [Док :Документ.срм_Событие]
FROM
  [Справочник.Контрагенты] Спр
  LEFT JOIN ПоследниеДокументы  as пДокументы
  ON Спр.ID = пДокументы.Клиент
");
Запрос.ВыполнитьЗапрос("DROP TABLE ПоследниеДокументы");
53 Sam1C
 
19.02.18
14:15
(46) Твой запрос похож с Djelf , но почему то лопатит час и заканчивается с ошибкой нехватки памяти. Не ужели это все из-за иннер джоин ?
select
    Спр.id [Клиентос:Справочник.Контрагенты]
   ,substr (Таб.МаксПозиция,-9)  [Док:Документ.срм_Событие]
from [Справочник.Контрагенты] Спр
left join(
select
    Док.шКонтрагент,
    max(idx_IDDOCDEF_DATE_TIME_IDDOC) МаксПозиция
from Журнал Жур
inner join [Документ.срм_Событие] Док
WHERE Жур.IDDOCDEF=:ВидДокумента.срм_Событие
group by Док.шКонтрагент) Таб on Таб.шКонтрагент=Спр.id
54 Sam1C
 
19.02.18
14:16
(53) с WHERE Жур.IDDOCDEF=:ВидДокумента.срм_Событие и без нее без разницы
55 Sam1C
 
19.02.18
15:04
(51) Спасибо за свежую версию
56 Ёпрст
 
19.02.18
16:32
(53) это не мой код
57 Ёпрст
 
19.02.18
16:33
ёпт..

select
    Спр.id [Клиентос:Справочник.Контрагенты]
   ,right(Таб.МаксПозиция,9)  [Док:Документ.срм_Событие]
from [Справочник.Контрагенты] Спр
left join(
select
    Док.Контрагент,
    max(idx_IDDOCDEF_DATE_TIME_IDDOC) МаксПозиция
from Журнал Жур
inner join [Документ.срм_Событие] Док on Док.iddoc = Жур.iddoc
group by Док.Контрагент) Таб on Таб.Контрагент=Спр.id
58 Ёпрст
 
19.02.18
16:34
ну и right замени на
substr(Таб.МаксПозиция,-9,9)
59 Djelf
 
20.02.18
20:17
Смысла в запросе в (52) особенно нет.
Смотрите план запроса в (29) explain`om.
sqlite сам при выполнении создает внутренние временные таблицы , сам их индексирует и сам склеивает.
Смысл в таком запросе может появится если переполняется память. Тогда да, придется создавать базу таблицу sqlite на диске, а не в памяти, но лучше выкручиваться как то по другому.
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.