[ОТВЕТИТЬ]
11.02.2012 19:42
AlexeyF
 
Подскажите куда копать?
Есть таблица с шапками документов - SUPERMAG.SERJ (ID документа и пара доп признаков)
Надо к каждому документу подтянуть спецификацию документа SMSpec, налоги SMSpecTax, карточка товара SMCard, себестоимость FFMapRep и при этом отфильтровать артикулы по условию принадлежности к каким то группам.
Когда у интересующих групп вложимость в дереве классификатора была одинаковая, использовалась конструкция следующего вида, и всё работало на ура: (запрос показывает все артикулы для документа БР420120101@45, за исключением групп '6789', '7891', '9400', '9402')
select * from
SUPERMAG.SERJ serj
left join SUPERMAG.FFMapRep f on f.SALEID=serj.ID
left join SUPERMAG.smspectax tax on f.SALEID=tax.DOCID and f.SALETYPE=tax.DOCTYPE and f.SALESPECITEM=tax.SPECITEM
where
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 10)
where ARTICLE=f.article
) not in ('6789', '7891', '9400', '9402')
and
serj.id = 'БР420120101@45'


Но потом понадобилось производить эти выборки для нескольких групп товаров с разной вложимостью дерева классификатора.
select * from SUPERMAG.SERJ serj
left join SUPERMAG.FFMapRep f on f.SALEID=serj.ID
left join SUPERMAG.smspectax tax on f.SALEID=tax.DOCID and f.SALETYPE=tax.DOCTYPE and f.SALESPECITEM=tax.SPECITEM
where
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 9)
where ARTICLE=f.article
)!='9092'
and
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 10)
where ARTICLE=f.article
) not in ('6789', '7891', '9400', '9402')
and
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 11)
where ARTICLE=f.article
) not in ('10093', '10095')
and
serj.id = 'БР420120101@45'


Это я думал, что если добавить ещё одно условие (select ...) not in ('xxx'), то всё будет как обычно. Но оказалось если в WHERE присутствуют два и более условия такого типа, соединённых AND'ом весь select возвращает погоду.
Т.е. в первом случае у меня все артикулы документа БР420120101@45, не принадлежащие группам '6789', '7891', '9400', '9402'. А во втором случае хотелось что бы все артикулы кроме уже 7-ти групп, но на выходе две записи и ни каких ошибок. При этом точно известно, что этих артикулов должно быть очень много.
Причём если наоборот нужно получить из документа артикулы, которые принадлежат группам, заменяем условия и AND на OR, объединяем скобочками и работает правильно.
where
((select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 9)
where ARTICLE=f.article
)='9092'
or
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 10)
where ARTICLE=f.article
) in ('6789', '7891', '9400', '9402')
or
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 11)
where ARTICLE=f.article
) in ('10093', '10095')
)

and
serj.id = 'БР420120101@45'


Подскажите как можно выкрутиться в этой ситуации ? Как ещё можно фильтровать по нескольким группам ?

Oracle Enterprise 10.2.0.4.0
11.02.2012 20:31
OlegON
 
сочувствую, поскольку объяснить то, что ты хочешь, трудно... рекомендации:
1) вырвать из задницы с мясом руки тому Сержу, который создает таблички в схеме SUPERMAG
2) отформатировать код, иначе с экрана его крайне трудно читать, а есть подозрение, что ты запутался в скобках или в том, что с чем сравниваешь
3) попробовать не использовать ANSI нотацию в пользу плюсовой, несмотря на то, что оракл продвигает ANSI, несколько раз спотыкался, что работает она как-то странно
11.02.2012 21:23
AlexeyF
 
Скобки проверялись, пере проверялись уже много раз. А вот различия синтаксиса я не в курсе был - вот с этим завтра буду плотно разбираться.
Погуглил - проблем скорее всего в ANSI
12.02.2012 18:19
AlexeyF
 
Так и оказалось.
заменил родительскую конструкцию вида:
select * from
SUPERMAG.SERJ serj
left join SUPERMAG.FFMapRep f on f.SALEID=serj.ID
left join SUPERMAG.smspectax tax on f.SALEID=tax.DOCID and f.SALETYPE=tax.DOCTYPE and f.SALESPECITEM=tax.SPECITEM
where
.........

на
select * from
SUPERMAG.SERJ serj,
SUPERMAG.FFMapRep f,
SUPERMAG.smspectax tax
where
f.saleid=serj.id and f.saleid=tax.docid and f.saletype=tax.doctype and f.salespecitem=tax.specitem
.........

Вот я бы с этим сам долго бы разбирался...
А что ошибками поддержки ANSI в 11-й версии, то же бывают глюки ???
12.02.2012 20:39
OlegON
 
Про 11ю не скажу, пока еще не рассматриваю ее в качестве основной, хотя больше по причине "руки не дошли". Но где-то спотыкался и на 9 и на 10ке. В 11й где-то была дока с уговорами перейти на ANSI, но мне плюсики роднее, да и вроде они пока не deprecated.
13.02.2012 07:16
Mtirt
 
А нельзя засунуть нужные карточки в ассортимент и выбирать по нему?
Чтобы упростить условие...
А в ассортимент можно последовательно, скриптом засунуть всё, что нужно или не нужно...
13.02.2012 08:51
AlexeyF
 
Про ассортимент идея мне в голову пришла, когда столкнулся с этим скрптом.
Если у меня получится, то буду дальше думать про упрощение-убыстрения оного, в том числе с пом ассортимента.
Сейчас нужно что бы он в принципе вернул то что надо.
(раньше было деление на одну группу и всё остальное, теперь неск групп и всё остальное).
Задача чуть чуть изменилась, а разработчик у нас не работает уже несколько месяцев.
13.02.2012 08:54
Mtirt
 
Ну тогда присоединяюсь к Олегу.
Приведи тот запрос, который неправильно работаеет в теге CODE, что-ли.
Сложно мне искать ошибку в твоем мелком шрифте...
13.02.2012 10:45
Mtirt
 
Такое условие тебя устроит?


Код:
 
(select id from SUPERMAG.sacardclass
minus
((select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 9)
where ARTICLE=f.article
)='9092'
and
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 10)
where ARTICLE=f.article
) in ('6789', '7891', '9400', '9402')
and
(select ts.id from SUPERMAG.SMCARD c
left join SUPERMAG.sacardclass t on t.ID=c.IDCLASS
left join SUPERMAG.SACARDCLASS ts on ts.TREE=SUBSTR(t.TREE,0, 11)
where ARTICLE=f.article
) in ('10093', '10095')
))
И я не совсем понимаю, зачем тебе два объединения с SACARDCLASS...
13.02.2012 10:59
vdm
 
Цитата:
Mtirt И я не совсем понимаю, зачем тебе два объединения с SACARDCLASS...
Присоединяюсь.
Выглядит очень странно, примерно как "отобрать группы с длиной(!) до 9-10-11 символов"
У вас tree так хитро устроено, что его длина что-то означает?
13.02.2012 17:13
AlexeyF
 
Цитата:
Mtirt Такое условие тебя устроит?
Не могу проверить в основном скрипте, т.к. в нём используется себестоимость, а она у меня сейчас в процессе расчёта (скрипт пока не работает)
Себестоимость посчитается, я выложу универсальный скрипт, который не привязан к моей базе будет и в скрипте покажу проблему, которую обойти не могу. Заодно буду очень рад идеям как скрипт облегчить.
Плз, погодите до завтра ????

Добавлено через 2 минуты 56 секунд
Цитата:
vdm Присоединяюсь.
Выглядит очень странно, примерно как "отобрать группы с длиной(!) до 9-10-11 символов"
У вас tree так хитро устроено, что его длина что-то означает?
Код стал разбирать то же не понял почему так сложно. Завтра положу скрипт, прошу на него взглянуть - может понятно будет почему так сделал программист.
14.02.2012 10:30
AlexeyF
 
Предлагаю посмотреть скрипт:
temp-4.sql
В нём готовый код, который к любому супермагу должен подойти. (наверное структура настолько сильно не меняется от версии, что бы этот код не смог заработать)
Там требуется только указать кассовый документ, продажи которого выводятся в seleсt.
Описание работы и вопросы в теле скрипта в комментариях.

Люди добрые, не хватает знаний у меня что бы разрешить данную проблему. Присоветуйте что поделать?
Либо помогите условие переделать. Нужно обработать попадание артикула в одну из 7-ми групп. Либо была правильная мысль - а можно его переделать на попадание/непопадание в один Ассортимент ?
14.02.2012 10:34
Mtirt
 
Вопрос у меня. В указанных в скрипте семи группах вложенные подгруппы есть? Или это последний уровень классификатора?
14.02.2012 10:35
AlexeyF
 
последний, нет подгрупп
14.02.2012 10:40
Mtirt
 
Давай для начала упростим запрос.
Код:
 select
f.saleid , f.article, f.saletype, f.saledate, f.SALENOVAT, tax.TAXRATE, tax.TAXSUM
from
SUPERMAG.FFMapRep f
SUPERMAG.SMCARD sm
where 
    f.saleid='Бр20120101@39' 
    and sm.article=f.article
    and f.RECTYPE=1
    and sm.idclass in ('9092', '6789', '7891', '9400', '9402', '10093', '10095')
Сколько артикулов? Ну и с not in соответственно...
14.02.2012 11:23
AlexeyF
 
in -- 2-ва "лишних" артикула
not in -- 1132 артикула, т.е. первоначальный скрипт без условий (1134) минус 2-ва "лишних" артикула

Я такие варианты сразу проверил - это само напрашивается. Результат получается совсем неожиданный. Я поэтому и понял, что я не понимаю ещё нюансов запроса к нескольким таблицам.
14.02.2012 11:29
Mtirt
 
Такой вариант:
Цитата:
select
f.article, sum(f.SALENOVAT)
from
SUPERMAG.FFMapRep f
SUPERMAG.SMCARD sm
where
f.saleid='Бр20120101@39'
and sm.article=f.article
and f.RECTYPE=1
and sm.idclass in ('9092', '6789', '7891', '9400', '9402', '10093', '10095')
group by f.article
14.02.2012 11:35
AlexeyF
 
Так же даёт сумму, по этим двум артикулам.

можно пока sum и group by f.article не делать, пока просто на том скелете с которого начали, если будет нормально показывать позиции проданного товара, я уже потом само суммирование с group верну.
14.02.2012 11:44
Mtirt
 
А почему не должен давать по этим двум артикулам?
Они есть в документе, насколько я понимаю. И принадлежат нужным группам. Нет?
14.02.2012 13:13
AlexeyF
 
Я не досмотрел один момент нехороший.
Артикулы производства должны находиться не в самих указанных 7-ми узловых группах, а в подгруппах. Именно поэтому используется фильтрация с отрезанием дерева артикулов SUBSTR(t.TREE,0, 10).

И вот тут была ошибка. По нашим стандартам карточки не могут находиться в узлах дерева артикулов, только в конечных папках. В процессе переноса карточек производства операторы "накосячили" и часть карточек оставили в узловых группах. Эти карточки и попадали в оба условия и эти карточки делали ошибку.

В процессе общения с Mtirt я наконец заметил эту ошибку, карточки перенесены куда должны были быть перенесены ранее, данные выгружаются корректные - уррааааа.....
14.02.2012 15:45
AlexeyF
 
Сам себя обманул.
Если товар находится в дочерней подгруппе, относительно какой нибудь из искомых 7-ми групп, то мой скрипт работает корректно. Если товар находится именно в этих 7-ми группах то выбираются ошибочные , лишние записи.

Поделитесь, как можно вытащить все продажи по кассовому документу для товаров, входящих в какие нибудь две группы, с подгруппами, и не входящими в эти же две группы с подгруппами.

Я уже всяко разно перепробовал варианты со своим скриптом, предложите кто нибудь свой вариант ???
14.02.2012 15:50
Mtirt
 
Наскоро тебе из старого запроса:
Цитата:
t.idclass in (select a.id from sacardclass a
where substr(a.tree,1,instr(a.tree, '.',1)-1) not in ('2','3', '4','5','6','7','8','17','18','19','20','25',
'28','29','30','33','34'))
Это группы первого уровня.
Для второго надо поменять функцию примерно на это: substr(a.tree,1,instr(a.tree, '.',2)-1) (Прости, прямо сейчас не тестировала) И в качестве условия указывать узлы дерева: ('2.1', '2.2')
14.02.2012 17:53
akonev
 
Цитата:
AlexeyF ...
Я уже всяко разно перепробовал варианты со своим скриптом, предложите кто нибудь свой вариант ???
Код:
select s.*
from smspec s,
     (select article from smcard c where c.idclass in(select id from sacardclass t where t.tree like '99.19.%' or t.tree like '99.9.%')) c2
where s.doctype='CS' and s.docid='CS20120210@31'
  and s.article=c2.article
или перенести все карточки в конечные группы и тупо перечислить их ID

или - если маркетинговые группы не используете - пометить все нужные группы И подгруппы в нем (я себе вьюшку рисовал, чтобы в отчетах вложенные группы наследовали установку от ближайшей старшей), потом по нему отбирать. один раз назначить ответственного и заставить его помечать группы при необходимости пересмотреть набор групп. но этот вариант лучше для каких-то глобальных выборок зарезервировать, которые весь классификатор должны на ломтики резать.

Добавлено через 6 минут 51 секунду
это были входящие. соответственно, не входящие
where c.idclass NOT in(select id
на втором уровне вложенности селектов.
14.02.2012 18:41
AlexeyF
 
В том и дело, что перечислять ID всех нужных групп, а их в подгруппах много. Лучше было бы указывать родительскую группу и нормально обрабатывать данные из неё самой и из дочерних.
Меня вот сейчас разбирает любопытство как отбираются карточки у супермага в разделе "карточки". Там мы выбираем группу и получаем список артикулов и из вложенных групп тоже. По идее это то что надо.

Завтра днём буду пробовать...
14.02.2012 20:13
OlegON
 
Так like у Андрея тебя чем не устроил?
15.02.2012 05:26
AlexeyF
 
Не то что не устроил, ещё не проверил. Сейчас со срочными вопросами разберусь и начну проверять все идеи, которые были предложены.
22.02.2012 09:58
Mtirt
 
Чем дело закончилось?
22.02.2012 11:41
AlexeyF
 
Дело не закончилось - в прошедшие выходные не успел сесть, надеюсь в эти выходные погоняю тесты.
Опции темы


Часовой пояс GMT +3, время: 13:19.

 

Форум сделан на основе vBulletin®
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot и OlegON
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.