Вход | Регистрация


1С:Предприятие :: 1С:Предприятие 7.7 и ранее

v7: Запрос на Sqlite

v7: Запрос на Sqlite
Я
   Sam1C
 
16.02.18 - 12:23
доброго дня! может кто подскажет идейку как выбрать для справочника контрагента последний документ определенного вида. Пока только в голову лезут выборка всех контрагентов и потом подзапросами по каждому выбирать Последний док. Но 10000 контрагентов 10000 подзапросов, что-то ни оптимально
 
 
   Ёпрст
 
1 - 16.02.18 - 12:27
(0)
обычный коррелированный подзапрос в селекте
   Ёпрст
 
2 - 16.02.18 - 12:29
ну или селект клиентос из справочника + лефт джоин (селект клиентос фром документ + гроуп бай  клиентосу и максимум дата и всё
   Sam1C
 
3 - 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
   Sam1C
 
4 - 16.02.18 - 13:18
(3) Что я делаю ни так? выдает все документы по каждому контрагенту, а не последний
   alxxsssar
 
5 - 16.02.18 - 13:22
(4) Группировки у тебя не излишние? По Менеджеру и Событию (Тем более я так понимаю это документ) зачем группировать?
   Sam1C
 
6 - 16.02.18 - 13:27
(5) согласен, щас оставлю только по Контрагенту по пробую
   alxxsssar
 
7 - 16.02.18 - 13:29
(6) из итоговых полей не забудь удалить, а то ошибка будет
   Sam1C
 
8 - 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
   alxxsssar
 
9 - 16.02.18 - 13:36
менеджера и событие. Иначе запрос ошибку выдаст, что они не участвуют в group by
   Sam1C
 
10 - 16.02.18 - 13:39
(9) не, тут пракатывает. в групп не обязательно все поля указывать которые есть в выборке. Короче запрос в (8) отработал на ура, данные верные, но 10 минут, это конечно не серьезно
 
 Рекламное место пустует
   alxxsssar
 
11 - 16.02.18 - 13:53
(10) поздравляю
   Sam1C
 
12 - 16.02.18 - 14:25
(11) поздравлять не с чем. очень долго работает
   Darych
 
13 - 16.02.18 - 14:33
(12) парси словарь, через ado к таблице дока скулевый запрос
   Ёпрст
 
14 - 16.02.18 - 15:31
Тебе нужно найти max(idx_IDDOCDEF_DATE_TIME_IDDOC) и по этому полю отфильтровать
   alxxsssar
 
15 - 16.02.18 - 15:41
(12) а сколько объектов в базе у тебя?
   alxxsssar
 
16 - 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
   Sam1C
 
18 - 16.02.18 - 16:17
(15) да не много 10000 контрагентов 50000 документов этого вида
   alxxsssar
 
19 - 16.02.18 - 16:25
(18) тогда даже для (8) это слишком долго. У меня 3 миллиона записей выбираются за 2,5 минуты
   alxxsssar
 
20 - 16.02.18 - 16:26
+(19) тоже с пересчетами и джойнами конечно
   Djelf
 
21 - 16.02.18 - 19:21
Отборы в журнале есть? Если есть по нужным критериям - можно использовать, должно ускорить.
> Но 10000 контрагентов 10000 подзапросов, что-то ни оптимально
Можно развернуть логику в обратную сторону - первым в запросе выбирать самую тяжелую таблицу и применить к ней все возможные условия, это видимо Журнал и джойнить к нему, а не наоборот.
100500 подзапросов к тяжелой таблице и убивают скорость.
   Злопчинский
 
22 - 16.02.18 - 20:23
Интересно за сколько 17 отработает
   Djelf
 
23 - 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мс т.к. движок начал понимать что если индекс упорядочен, то просматривать всю таблицу не имеет смысла.
   Djelf
 
24 - 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)


   mistеr
 
25 - 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
?
   Djelf
 
29 - 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 лишний же
   Djelf
 
31 - 17.02.18 - 15:59
(30) Да, перестраховался ;(
   SleepyHead
 
32 - 17.02.18 - 18:08
Чем-то мне это все напоминает анекдот про Ржевского и господ офицеров, развлекавшихся с девушкой на бильярдном столе.

Господа, с вами все в порядке? Штатным языком 1с77 задача решается в три строки кода.
   Злопчинский
 
33 - 17.02.18 - 19:22
(32) жжошь!
 
 
   Djelf
 
34 - 17.02.18 - 19:24
Ну вот пришел SleepyHead и все испортил ;(
А столько еще идей было...
   Злопчинский
 
35 - 17.02.18 - 19:32
СделатьВсе()
   Ёпрст
 
36 - 18.02.18 - 19:38
(32) Ну напиши нам, эти строки,
 так, на поржать
   Aleksey
 
37 - 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
разве что перебор справочника клиентосов и для каждого выбратьпозначению с условием на вид дока в перебое..
но, это не наш метод, слишком долго
   Aleksey
 
42 - 18.02.18 - 20:21
Ну я так понимаю нужно просто в карточки клиента вывести список, чтобы как в 8-ке
   Sam1C
 
43 - 18.02.18 - 20:24
(22) В (17) в подзапросе нет отбора по виду документа по этому он больше часа лопатит. И наверно нет функции right в SQlite вместо нее substr, substr (Таб.МаксПозиция,-9) походу делать так нужно.
   Sam1C
 
44 - 18.02.18 - 20:27
Запрос в (8) работает 10 минут как говорилось выше, а вот (29) 18 секунд, спасибо  Djelf.
   Sam1C
 
45 - 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) это лишнее
   SleepyHead
 
49 - 19.02.18 - 12:27
(38) "Нет графы отбора"

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

(45) Не доводил до идеала. Все равно это видимо только часть запроса.
   Sserj
 
52 - 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 ПоследниеДокументы");
   Sam1C
 
53 - 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
   Sam1C
 
54 - 19.02.18 - 14:16
(53) с WHERE Жур.IDDOCDEF=:ВидДокумента.срм_Событие и без нее без разницы
   Sam1C
 
55 - 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)
   Djelf
 
59 - 20.02.18 - 20:17
Смысла в запросе в (52) особенно нет.
Смотрите план запроса в (29) explain`om.
sqlite сам при выполнении создает внутренние временные таблицы , сам их индексирует и сам склеивает.
Смысл в таком запросе может появится если переполняется память. Тогда да, придется создавать базу таблицу sqlite на диске, а не в памяти, но лучше выкручиваться как то по другому.


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