Reputation: 3094
I have created a table to cater to some customer requirements, and have to write a query on the data to be stored in the table. I am not able to figure out an optimal way to write my query.
My table is structured like:
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
The user specifies a value of C1
and then values for C2
and C3
(simply one value for c2 and one for c3). Let's say that I have to return the rate column as an output. The last column in the table structure is OPERATOR
, which tells me whether the C2
and C3
values should be AND
or OR
ed.
I am facing problem in determining the opearator to be used. A user can select any value at her discretion for lower and upper limits. I tried basing my operator selection only on one group - let's say C2
, but then that is not right, as I need to evaluate all variabels input by the user to get the correct operator.
Let's say that a user enters a value of 0
for c2 and enters a value of 25000
for c3 for c1 = 1
. Since the values of c3 correspond to the entry with opeartor value of OR
, I should OR
the c2 and c3 limit values. In short, if a record with OR
operator is found, I have to OR
the c2 and c3 groups.
You can check SQLFiddle for table structure http://www.sqlfiddle.com/#!4/f9bf6/11
Upvotes: 0
Views: 51
Reputation: 311143
A quick and dirty solution could be to add a condition on the operator
field.
Using the :
notation to signify passed parameters:
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)
)
)
EDIT:
Note that there's a lot of code duplicity handling null
s with a between
operation. If you can alter the database, I'd add a helper function that does this:
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;
Upvotes: 1