无法弄清楚查询

时间:2014-01-27 09:29:45

标签: sql oracle oracle11g

我已经创建了一个表来满足一些客户的需求,并且必须对要存储在表中的数据进行查询。我无法找出编写查询的最佳方式。

我的表结构如下:

c1   c2_lower_limit   c2_upper_limit   c3_lower_limit   c3_upper_limit   rate   operator
1    0                10000            0                20000            10     AND
1    10000            50000            20000            30000            20     OR
1    50000            NULL             30000            NULL             30     OR 
2    0                10000            0                20000            10     AND
2    10000            50000            20000            30000            20     OR
2    50000            NULL             30000            NULL             30     OR

用户指定C1的值,然后指定C2C3的值(c2只有一个值,c3有一个值)。假设我必须将rate列作为输出返回。表结构中的最后一列是OPERATOR,它告诉我C2C3值应该是AND还是OR

我在确定要使用的运算符时遇到问题。用户可以根据自己的判断选择任何值以获得下限和上限。我尝试仅将操作员选择基于一个组 - 让我们说C2,但那时这是不对的,因为我需要评估用户输入的所有变量,以获得正确的运算符。

假设用户为c2输入0的值,并为25000的c3输入值c1 = 1。由于c3的值对应于opeartor值为OR的条目,因此我应该OR c2和c3限制值。简而言之,如果找到OR运算符的记录,我必须OR c2和c3组。

您可以检查SQLFiddle表格结构http://www.sqlfiddle.com/#!4/f9bf6/11

1 个答案:

答案 0 :(得分:1)

快速而肮脏的解决方案可能是在operator字段上添加条件。

使用:表示法表示传递的参数:

SELECT *
FROM   my_table
WHERE  c1 = :c1 
AND    ((operator = 'AND' 
         AND
         (:c2 BETWEEN c2_lower_limit AND c2_upper_limit OR
          (:c2 >= c2_lower_limit AND c2_upper_limit IS NULL) OR
          (c2_lower_limit IS NULL AND :c2 < c2_upper_limit) 
         AND
         (:c3 BETWEEN c3_lower_limit AND c3_upper_limit OR
          (:c3 >= c3_lower_limit AND c3_upper_limit IS NULL) OR
          (c3_lower_limit IS NULL AND :c3 < c3_upper_limit) 
        )
       OR
        (operator = 'OR' 
         AND
         (:c2 BETWEEN c2_lower_limit AND c2_upper_limit OR
          (:c2 >= c2_lower_limit AND c2_upper_limit IS NULL) OR
          (c2_lower_limit IS NULL AND :c2 < c2_upper_limit) 
         OR
         (:c3 BETWEEN c3_lower_limit AND c3_upper_limit OR
          (:c3 >= c3_lower_limit AND c3_upper_limit IS NULL) OR
          (c3_lower_limit IS NULL AND :c3 < c3_upper_limit) 
        )
       )

修改
请注意,有很多代码重复性处理带有null操作的between。如果你可以改变数据库,我会添加一个辅助函数来执行此操作:

CREATE OR REPLACE FUNCTION null_safe_between 
(eval NUMBER, lower NUMBER, upper NUMBER) 
RETURN BOOLEAN
DETERMINISTIC
BEGIN
    RETURN eval BETWEEN lower_limit AND upper_limit OR
           (eval >= lower_limit AND upper_limit IS NULL) OR
           (lower_limit IS NULL AND eval < upper_limit);
END;