OR约束的SQL语句中的条件列

时间:2009-09-21 10:59:31

标签: sql oracle

这个问题是关于SQL中的一般技术,我无法弄清楚如何最好地实现我目前对该语言的理解。

请注意,这将针对Oracle运行,以防任何特定于供应商的功能特别有用,但我希望有一种很好的方法可以使用“纯”SQL执行此操作。

问题的简短版本:如果我对查询有OR条件,以便检查我的“主”表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,其中包含orderclient(相应表的两个主键)和另一列multiplier的列,这是一个介于0.0和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 个答案:

答案 0 :(得分:5)

如果并非所有订单都有关联的managed_order,那么您需要使用外部联接。然后你可以处理没有这样的乘数:

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。

答案 1 :(得分:2)

您可以使用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 = ?

答案 2 :(得分:2)

你可以使用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

答案 3 :(得分:1)

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 = ?