ORACLE SQL: нужно сложить два значения, но одно может не существовать ... Возможно ли это? - PullRequest
2 голосов
/ 18 ноября 2008

У меня были проблемы с копированием старых файлов ASP в более новый код .NET 2.0. Одна из задач - объединить 4-5 операторов SQL в один. Несмотря на то, что я сделал это и добился некоторого успеха в повышении производительности, Oracle стал для меня новой сумкой. Эта проблема, однако, превосходит мои собственные навыки SQL, поскольку я не делал этого раньше.

По сути, у меня КОЛИЧЕСТВО в одной таблице из группы продаж. Каждая продажа имеет целочисленное значение. К каждой продаже также прикреплен ПУНКТ. У каждого ПУНКТА есть фактор КОНВЕРСИИ, например, если я продам 1 пакетик чего-либо = 10 наборов чего-либо Поэтому, когда я запускаю отчет и хочу узнать конечную стоимость, мне нужно взять каждую продажу и ее количество и умножить ее на коэффициент пересчета. Большинство из них простые 1 к 1, так что в основном это 25 * 1, 30 * 1 и т. Д.

Моя проблема в том, что в моих записях были прошлые продажи, в которых ПУНКТ был удален из нашей системы, поэтому фактор КОНВЕРСИИ не существует. Эти записи удаляются из моего запроса, потому что ФАКТОР исчез.

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code 
FROM salesdetails rth, salesheader rsh
WHERE rsh.number = rth.number(+)
AND rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rth.sale_code IN('ITEM07')
AND rth.c_code = 'WLMT'
AND rsh.year = '2008'

Это мой первый запрос. Если я добавлю преобразование в:

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code, rth.quantity * cf.conversion
FROM salesdetails rth, salesheader rsh, conversionfactor cf
WHERE rsh.number = rth.number(+)
AND rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rth.sale_code IN('ITEM07')
AND rth.c_code = 'WLMT'
AND rsh.year = '2008'
AND cf.item_code = rth.item_code
and cf.code = '01'
and cf.loc_code = '00001'

Это работает до определенной степени. В нем перечислены все те же записи, но в нем отсутствуют записи, в которых не существовал фактор CONVERSION. Могу ли я в любом случае включить те записи, в которых ФАКТОР не существовал во втором запросе, если не считать перехода строка за строкой и преобразования таким образом.

Ответы [ 9 ]

2 голосов
/ 18 ноября 2008

Вы также можете использовать функцию Coalesce с подзапросом ...

оценивает каждый аргумент по очереди и возвращает первый найденный аргумент, который не является нулевым. >

Select D.CODE, D.NUMBER, D.QUANTITY, D.sale_code, 
    D.quantity * Coalesce((Select conversion 
                           From conversionfactor
                           Where item_code = H.item_code
                              And code = '01'
                              And loc_code = '00001'), 1.0)
From salesheader H
   Left Join salesdetails D
     On D.Number = H.Number
Where H.customer_code = '05'
   And H.r_code = '01'
   And H.location_code = '12'
   And H.year = '2008'
   And D.sale_code In ('ITEM07')
   And D.c_code = 'WLMT'

замените значение 1,0 в конце подзапроса на любое значение «по умолчанию» коэффициента преобразования, если записи больше нет в таблице коэффициентов преобразования ...

1 голос
/ 18 ноября 2008

Не имеет смысла внешнее присоединение от rsh к rth, но затем inner присоединение от rth к cf. Сделайте их обоими внешними соединениями. Кроме того, символ (+) должен появляться на «внешней» стороне всех условий соединения для rth:

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code,
       rth.quantity * cf.conversion
FROM salesdetails rth, salesheader rsh, conversionfactor cf
WHERE rsh.number = rth.number(+)
AND rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rth.sale_code (+) IN('ITEM07')
AND rth.c_code (+) = 'WLMT'
AND rsh.year = '2008'
AND cf.item_code (+) = rth.item_code
and cf.code (+) = '01'
and cf.loc_code (+) = '00001'

Кстати, это очень старомодный синтаксис. Почему бы не использовать более современные:

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code,
       rth.quantity * cf.conversion
FROM salesheader rsh
LEFT OUTER JOIN salesdetails rth
   ON  rsh.number = rth.number
   AND rth.sale_code IN ('ITEM07')
   AND rth.c_code = 'WLMT'
LEFT OUTER JOIN conversionfactor cf
   ON  cf.item_code = rth.item_code
   AND cf.code = '01'
   AND cf.loc_code = '00001'
WHERE rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rsh.year = '2008'
0 голосов
/ 28 сентября 2013

Если вы работаете с нулевыми значениями и числами, подумайте об использовании функции "coalesce", когда из списка первое ненулевое значение возвращается в качестве результата.

0 голосов
/ 20 ноября 2008

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

Как,

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code, rth.quantity * NVL(cf.conversion,1)
FROM salesdetails rth, salesheader rsh, conversionfactor cf
WHERE rsh.number = rth.number(+)
AND rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rth.sale_code IN('ITEM07')
AND rth.c_code = 'WLMT'
AND rsh.year = '2008'
AND cf.item_code = rth.item_code
and cf.code = '01'
and cf.loc_code = '00001'

Дважды проверьте синтаксис NVL. Прошло пару лет с тех пор, как я работал с Oracle.

0 голосов
/ 18 ноября 2008

На самом деле, вы правы насчет ВНЕШНЕГО СОЕДИНЕНИЯ. Я думал, что в том, что он делал, была техническая составляющая, но я точно понимаю, почему это все еще не включало ценность. Два других критерия должны быть (+), чтобы включить NULL. Я объединил это с COALESCE, и это, кажется, работает.

0 голосов
/ 18 ноября 2008

Я полагаю, что SQL предполагает, что у меня нулевая запись. У меня нет записи вообще, когда преобразования не существует. Если бы я мог найти способ вернуть ноль для тех преобразований, которые не существуют в моей БД, я мог бы это сделать.

0 голосов
/ 18 ноября 2008

Я думаю, что это должно работать. Предполагается, что коэффициент преобразования равен 1, когда он не существует

select 
    rth.code, rth.number, rth.quantity, rth.sale_code, rth.quantity * coalesce(cf.conversion,1)
from 
    salesdetails rth
    inner join  salesheader rsh on rsh.number = rth.number
    left join conversionfactor cf on cf.item_code = rth.item_code
where 
rsh.customer_code = '05'
and rsh.r_code = '01'
and rsh.location_code = '12'
and rth.sale_code in('item07')
and rth.c_code = 'wlmt'
and rsh.year = '2008'
and cf.code = '01'
and cf.loc_code = '00001'
0 голосов
/ 18 ноября 2008

Нет, я считаю, что OUTER JOIN не работает, потому что записи на самом деле нет. Он не нулевой, просто его больше не существует.

0 голосов
/ 18 ноября 2008

Сейчас я не могу получить доступ к Oracle. Проверьте этот запрос:

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code, rth.quantity * cf.conversion
FROM salesdetails rth, salesheader rsh, conversionfactor cf
WHERE rsh.number = rth.number(+)
AND rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rth.sale_code IN('ITEM07')
AND rth.c_code = 'WLMT'
AND rsh.year = '2008'
AND rth.item_code  =  cf.item_code (+)
and cf.code = '01'
and cf.loc_code = '00001'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...