Имя: Пароль:
1C
1C 7.7
v7: 1SQLite: Помогите с запросом к справочнику товаров
0 PVL09
 
19.08.16
07:51
Ув. господа! Нужна ваша помощь с запросом к справочнику товаров. Суть запроса - получить список товаров, удовлетворяющего некоторым условиям:
1) Отбор по группам товаров - необязательное, группа одна или несколько, уровни могут быть разные, 1-2 по иерархии;
2) Отбор по реквизиту группы ("Куратор","Справочник.Кураторы",необязательный, один или несколько), заполнен только на произвольном уровне (1-3), но нижележащие уровни должны входить в выборку;
3) Отбор по реквизиту элемента ("Категория", "Справочник.Категории", необязательный), заполнен у всех товаров.
1 PVL09
 
19.08.16
07:54
Накидал запрос, но как-то он криво работает - при исключении одного из критериев зависает до бесконечности.
Вот текст запроса:
SELECT
    Таб.code,
    Таб.Descr,
    СпрТ.id [Объект :Справочник.Товары],
    Таб.Куратор [Куратор :Справочник.Кураторы]
FROM [Справочник.Товары] СпрТ
    inner join (

SELECT
    СпрТов.PARENTEXT,
    СпрТов.code,
    СпрТов.Descr,
    СпрТов.id,
    СпрТов.Куратор
    ,CASE
    WHEN Тов3.ID<>'     0   ' THEN Тов3.ID
    WHEN Тов2.ID<>'     0   ' THEN Тов2.ID
    WHEN Тов1.ID<>'     0   ' THEN Тов1.ID
    ELSE СпрТов.ID
END ОбъектГ
FROM
    Справочник_Товары СпрТов
    left join [Справочник.Товары] Тов1 on (Тов1.PARENTEXT='     3   ') and (Тов1.ParentID = СпрТов.ID) and (Тов1.IsFolder = 1)
    left join [Справочник.Товары] Тов2 on (Тов2.PARENTEXT='     3   ') and (Тов2.ParentID = Тов1.ID) and (Тов2.IsFolder = 1)
    left join [Справочник.Товары] Тов3 on (Тов3.PARENTEXT='     3   ') and (Тов3.ParentID = Тов2.ID) and (Тов3.IsFolder = 1)
WHERE (СпрТов.PARENTEXT='     3   ') and
    (СпрТов.IsFolder = 1)
and (СпрТов.ID IN (SELECT Val FROM ТабТов))
and (СпрТов.Куратор IN (SELECT Val FROM ТабКур))

      ORDER by 1) as Таб on Таб.ОбъектГ=СпрТ.ParentID
WHERE (СпрТ.PARENTEXT='     3   ') and (СпрТ.IsFolder = 2)  and (СпрТ.Категория IN (SELECT Val FROM ТабКат))
2 PVL09
 
19.08.16
07:56
вот что выдает отладка:
, idx_ID char(9) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_CODE char(26) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_DESCR char(119) collate _1C default null
, idx_CODE char(7) collate _1C default null
, idx_DESCR char(100) collate _1C default null
, idx_Артикул char(40) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_Артикул char(59) collate _1C default null
, idx_ЕдиницаИзмерения_DESCR char(109) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_ЕдиницаИзмерения_DESCR char(128) collate _1C default null
, idx_Категория_DESCR char(109) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_Категория_DESCR char(128) collate _1C default null
, idx_ОЕМ char(20) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_ОЕМ char(39) collate _1C default null
, idx_АМатрица_DESCR char(109) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_АМатрица_DESCR char(128) collate _1C default null
, idx_Куратор_DESCR char(109) collate _1C default null
, idx_PARENTEXT_PARENTID_ISFOLDER_Куратор_DESCR char(128) collate _1C default null
)
szName SC16
Подбор индекса для таблицы SC16 :
    Ограничения: PARENTEXT=; ISFOLDER=;
    Найдено в кэше
    Выбран индекс PCODE: PARENTEXT+PARENTID+STR(ISFOLDER,1)+UPPER(CODE)
    Стоимость: 18
szName SC16
Подбор индекса для таблицы SC16 :
    Ограничения: PARENTEXT=; ISFOLDER=; SP647[Категория]=;
    Найдено в кэше
    Выбран индекс PCODE: PARENTEXT+PARENTID+STR(ISFOLDER,1)+UPPER(CODE)
    Стоимость: 18
szName SC16
Подбор индекса для таблицы SC16 :
    Ограничения: PARENTEXT=; ISFOLDER=;
    Упорядочить: PARENTEXT,
    Найдено в кэше
    Выбран индекс PCODE: PARENTEXT+PARENTID+STR(ISFOLDER,1)+UPPER(CODE)
    Попадает в сортировку
    Стоимость: 18
szName SC16
Подбор индекса для таблицы SC16 :
    Ограничения: PARENTEXT=; ISFOLDER=; ID=; SP74342[Куратор]=;
    Упорядочить: PARENTEXT,
    Найдено в кэше
    Выбран индекс PCODE: PARENTEXT+PARENTID+STR(ISFOLDER,1)+UPPER(CODE)
    Попадает в сортировку
    Стоимость: 18
szName SC16
Подбор индекса для таблицы SC16 :
    Ограничения: PARENTEXT=; PARENTID=; ISFOLDER=;
    Найдено в кэше
    Выбран индекс PCODE: PARENTEXT+PARENTID+STR(ISFOLDER,1)+UPPER(CODE)
    Стоимость: 16
szName SC16
Подбор индекса для таблицы SC16 :
    Ограничения: PARENTEXT=; PARENTID=; ISFOLDER=;
    Найдено в кэше
    Выбран индекс PCODE: PARENTEXT+PARENTID+STR(ISFOLDER,1)+UPPER(CODE)
    Стоимость: 16
szName SC16
Подбор индекса для таблицы SC16 :
    Ограничения: PARENTEXT=; PARENTID=; ISFOLDER=;
    Найдено в кэше
    Выбран индекс PCODE: PARENTEXT+PARENTID+STR(ISFOLDER,1)+UPPER(CODE)
    Стоимость: 16
1SQLite: 154.48 сек.
3 Ёпрст
 
гуру
19.08.16
08:00
(0)
1SQLite УложитьОбъекты не  отрабатывает
читай последние посты и.. переписывай запрос
4 Ёпрст
 
гуру
19.08.16
08:03
(0) заместо case лучше писать
coalesce(Тов3.ID, Тов2.ID, Тов1.ID,СпрТов.ID) ОбъектГ

и сравнивать с пустымИД - не верно, там null будет, если че, а не пустой ИД.
5 Ёпрст
 
гуру
19.08.16
08:04
писать
Тов1.PARENTEXT='     3   ') - моветон, пиши по-русски:
Тов1.PARENTEXT=:ВыбВладелец
6 Ёпрст
 
гуру
19.08.16
08:06
ORDER by 1 - это выкинь
7 Ёпрст
 
гуру
19.08.16
08:07
На счет куратора - у тебя опять неверно, это реквизит группы
8 Ёпрст
 
гуру
19.08.16
08:08
вот эти условия:
and (Тов1.IsFolder = 1)  - не верные. Так ты получаешь только группы, а на все элементы унутри групп кладешь с прибором
9 PVL09
 
19.08.16
08:35
Не успеваю читать..
(5) принципиально это ничего не поменяет же, владелец не меняется..
(7) сначала получаю группы а потом к ним цепляю товары.. так не канает?
10 Ёпрст
 
гуру
19.08.16
08:46
(9) канает, не заметил, что ты иннер джоин потом лепишь по as Таб on Таб.ОбъектГ=СпрТ.ParentID
11 Ёпрст
 
гуру
19.08.16
08:47
всё равно, я бы всё переписал по-другому, с учетом (3).
12 Ёпрст
 
гуру
19.08.16
08:47
но у тебя основная ошибка - case твой
13 PVL09
 
19.08.16
08:48
(12)  Здесь я полностью согласен! Сейчас пробую..
14 PVL09
 
19.08.16
09:37
(11) Как бы ты переделал? В любом случае нужно сначала сделать отбор по группам, а потом к ним товары цеплять.. Или есть другие варианты? А ИндексированнаяТаблица никак здесь не поможет?
15 PVL09
 
19.08.16
10:30
(11) Что-то опять не удалось УложитьОбъекты..
16 Djelf
 
гуру
19.08.16
17:07
Ага, в (7) верно замечено. Куратор - реквизит группы.
(0) Логика с кураторами то какая?
Если в группе1 Иванов, а в подчиненной группе2 Петров, то при выборе Иванова что должно выводится? Группа1 или еще и Группа2
17 PVL09
 
20.08.16
09:16
(16) Куратор ставится на 2 или 3 (реже) уровнях, и они не пересекаются. Это привязка групп товаров к менеджеру закупок
18 Djelf
 
гуру
20.08.16
17:34

Условия сам прилепишь...

WITH RECURSIVE Cte(ID,PARENTID,PARENTEXT,ISFOLDER,Куратор) AS (

    SELECT
        СпрТ.ID,СпрТ.PARENTID,СпрТ.PARENTEXT,СпрТ.ISFOLDER,СпрТ.Куратор
    FROM Справочник_Товары AS СпрТ
    WHERE СпрТ.ID = '    1J   '

    UNION SELECT
        Спр.ID,Спр.PARENTID,Спр.PARENTEXT,Спр.ISFOLDER,
        CASE WHEN Cte.Куратор = :ПустойИД THEN Спр.Куратор ELSE Cte.Куратор END
    FROM Cte as Cte
    INNER JOIN [Справочник_Товары] AS Спр
        ON Cte.ID = Спр.PARENTID
        AND Cte.PARENTEXT = Спр.PARENTEXT
        AND    Cte.ISFOLDER=1
)
-- INSERT into tmp
SELECT
    Cte.PARENTEXT [Владелец $Справочник.ТипыБизнеса]
    ,Cte.PARENTID [Родитель $Справочник.Товары]
    ,СпрТ.DESCR [НаименованиеТовара]
    ,Cte.ID  [Товар $Справочник.Товары]
    ,Cte.ISFOLDER [ЭтоГруппа]
    ,Cte.Куратор [Куратор $Справочник.Кураторы]
    ,СпрТ.DESCR [НаименованиеКуратора]
    
FROM Cte
LEFT JOIN Справочник_Товары AS СпрТ ON СпрТ.ID=Cte.ID
LEFT JOIN Справочник_Кураторы AS СпрК ON СпрК.ID=СпрТ.Куратор
WHERE Cte.ISFOLDER=2

19 PVL09
 
20.08.16
22:54
(18) Спасибо! Непонятно как, но работает! И очень быстро!
20 Djelf
 
гуру
20.08.16
23:06
Кури cte! По этим ссылка нормально объясняется:
http://info-comp.ru/obucheniest/495-the-with-in-t-sql-or-common-table-expression.html
http://postgresql.ru.net/manual/queries-with.html

То что там про cte в mssql и postgesql - не существенно.
21 Djelf
 
гуру
20.08.16
23:09
Если будут тормоза при накладывании условий по IN пробуй заменить
WHERE Таб.ID IN (ЧтоТоТам)
на
WHERE +Таб.ID IN (ЧтоТоТам)
Это отключит оптимизацию по IN, которая иногда в sqlite дурит по страшному.
22 orefkov
 
21.08.16
00:45
(18) а 1sqlite умеет cte? Ошеломлен, если честно.
23 orefkov
 
21.08.16
00:50
+(22)
Прочитал другую ветку, вопрос снимаю, равно как и шляпу :) Отличная работа.
24 Djelf
 
гуру
21.08.16
01:09
(23) Халтура, Шеф! Халтура!
Была бы отличная, я бы разобрался как индекс по двум полям ставить...
Буду думать 1sqlite дальше, возможно и достигну следующий степени просветления.
25 PVL09
 
21.08.16
08:26
(21),(22) Спасибо вам, парни! Да пребудет с вами сила просветления! ;-)