Условные столбцы в операторах SQL с ограниченными OR - PullRequest
1 голос
/ 21 сентября 2009

Этот вопрос касается общего метода в SQL, который я не могу понять, как лучше всего достичь с моим текущим пониманием языка.

Обратите внимание, что это будет работать с Oracle, в случае, если какие-либо специфичные для поставщика функции будут особенно полезны, хотя я ожидаю, что есть хороший способ сделать это с "чистым" SQL.

Краткая версия вопроса: если у меня есть условие ИЛИ для запроса, такое, что я проверяю, что значение в моей "основной" таблице A соответствует значению в таблице B или в таблице C, что является лучшим способом условно изменить (например, умножить) селекторы операторов, если значение было найдено в таблице C, а не в таблице B?

Длинная версия (с примером): В настоящее время у меня есть запрос, который выглядит примерно так (он намного сложнее, но это основная структура):

select o.value, /* other stuff... */
  from orders o,
       clients c
 where o.client = c.pkey
   and c.name = ?

Все хорошо. Однако теперь представьте, что некоторым клиентам разрешено действовать от имени других - но из-за комиссий за обработку или некоторых логических сделок, осуществляемых таким образом, не имеют полной стоимости. Таким образом, есть таблица managed_orders со столбцами для order, client (оба первичных ключа к соответствующим таблицам) и другой столбец multiplier, который представляет собой число с плавающей запятой между 0,0 и 1,0, представляющее пропорцию значения заказа это должно быть "перенесено".

Правильно - поэтому изменение вышеуказанного запроса для отображения заказов, которые либо принадлежат данному клиенту, либо управляются ими для кого-то другого, довольно просто. Однако мне нужно было бы умножить селектор o.value на управляемый ордер на multiplier , если это управляемый ордер, но если это классический прямой ордер, то в этом нет необходимости (или, эквивалентно, мы могли бы умножить на 1,0).

select o.value * m.multiplier /* Will not work in all cases */, /* other stuff... */
  from orders o,
       clients c,
       managed_orders m
 where (o.client = c.pkey or m.order = o.pkey)
   and c.name = ?
   and m.client = c.pkey

Как лучше всего добиться этого условного умножения?

Ответы [ 4 ]

5 голосов
/ 21 сентября 2009

Если не все заказы имеют связанный с этим управляемый заказ, вам необходимо использовать внешнее соединение. Затем вы можете справиться с отсутствием множителя следующим образом:

select o.value * COALESCE(m.multiplier,1)
from orders o
left outer join managed_orders m on m.order = o.pkey
left outer join clients c on (o.client = c.pkey or m.client = c.pkey)
where c.name = ?

COALESCE гарантирует, что если множителя нет, вместо него используется константа 1.

2 голосов
/ 21 сентября 2009

Не могли бы вы использовать UNION для получения необходимого набора результатов.

что-то вроде

Select o.value, ... 
FROM Orders o, clients c
WHERE o.client = c.pkey
and c.name = ?
UNION
SELECT o.value * m.multiplier, ...
FROM Orders o, clients c, managed_orders m
WHERE m.order = o.pkey
AND c.name = ?
AND m.client = c.pkey
2 голосов
/ 21 сентября 2009

вы можете использовать OUTER JOIN для условного объединения двух таблиц. Предполагая, что у всех заказов есть клиент и что в таблице MANAGED_ORDERS присутствуют только управляемые заказы, модификатор будет применяться только в том случае, если это управляемый заказ:

SELECT o.value * nvl(m.multiplier, 1)
  FROM orders o
  JOIN client c ON (o.client = c.pkey)
  LEFT JOIN managed_orders ON o.pkey = m.order
WHERE c.name = ?
1 голос
/ 21 сентября 2009

Как насчет CASE?

SELECT o.value * (CASE 
                     WHEN m.pkey IS NOT NULL THEN m.managed_multiplier /* Might need */
                     ELSE 1.0                                  /* some tweaking here */ 
                 END)
    /* , other stuff... */
FROM orders o
    LEFT JOIN clients c ON (o.client = c.pkey)
        LEFT JOIN managed_orders m ON (m.order = o.pkey)
WHERE 
   c.name = ?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...