Problem using multiple CASE in WHERE clause - oracle

I'm trying to create an SQL that added two more conditions when the specific column(value) is matched.
Example:
SELECT
COLUMN_NAME
FROM
TABLE
WHERE
NAME_COLUMN = 'NAME'
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOLD_COLUMN
END = 1
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOLD_COLUMN_1
END = 1
It is working when AGE = 18 it will return value that ADULTHOOLD_COLUMN = 1 and ADULTHOOLD_COLUMN_1 = 1
but when age is not equal to 18 it will not return any rows.
I was expecting that all of the data(with 1 or 0) will return.
ADULTHOOLD_COLUMN(Value in db is 1 or 0)
ADULTHOOLD_COLUMN_1(Value in db is 1 or 0)

Sounds a bit strange, but ok, looks like you need else:
SELECT
COLUMN_NAME
FROM
TABLE
WHERE
NAME_COLUMN = 'NAME'
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOD_COLUMN
ELSE 1
END = 1
AND
CASE
WHEN AGE = '18'
THEN ADULTHOOD_COLUMN_1
ELSE 1
END = 1
Or maybe just to make it more readable:
SELECT
COLUMN_NAME
FROM
TABLE
WHERE
NAME_COLUMN = 'NAME'
AND (AGE is null OR AGE!='18' OR AGE = '18' AND ADULTHOOD_COLUMN = 1)
AND (AGE is null OR AGE!='18' OR AGE = '18' AND ADULTHOOD_COLUMN_1 = 1)
PS. Are you sure that AGE is not number? If that's a number datatype, you need to replace '18' to 18

Related

Orcale - Missing Right Paranthesis

I am trying to run an oracle query using, Case when and Sum together, It gives me an error saying I am missing the right paranthesis.
The query below,
SELECT c.Customer_name,
CASE WHEN SUM(status = 'DELIVERED') = count(*) THEN 'A'
WHEN SUM(status = 'DELIVERED') > 0 THEN 'B'
WHEN SUM(status = 'SUBMITTED') > 0 THEN 'C'
ELSE 'No Match'
END AS Match
FROM Customer_Order c
group by c.Customer_name order by c.Customer_name;
Changed my query to look like this and it says, I am missing keyword
SELECT c.Customer_name,
CASE WHEN SUM(c.status) = 'DELIVERED' = (count(c.status)) THEN 'A'
WHEN SUM(c.status) = 'DELIVERED' > 0 THEN 'B'
WHEN SUM(c.status) = 'SUBMITTED' > 0 THEN 'C'
ELSE 'No Match'
END AS Match
FROM Customer_Order c
group by c.Customer_name order by c.Customer_name;
Ok, what I think you are trying to do includes counting all the cases where status = 'DELIVERED' and status = 'SUBMITTED' and then comparing those with something to determine what the outcome is. But you can't sum a conditional expression like status = 'DELIVERED' so you need to do it in two steps: one to make a number out of the conditional and one to compare the sum with something.
Step 1: To count the cases where status = 'DELIVERED' you need a column that is 1 when the status is DELIVERED and 0 when it is not (and the same with 'SUBMITTED'). That way you have numbers to sum. So the data we want to run your query on is:
SELECT *,
CASE WHEN status = 'SUBMITTED' THEN 1 ELSE 0 END AS Is_submitted,
CASE WHEN status = 'DELIVERED' THEN 1 ELSE 0 END AS Is_delivered
FROM Customer_order
Step 2: Now we can use your query on the results of Step 1:
SELECT
c.Customer_name,
CASE WHEN SUM(c.delivered) = count(*) THEN 'A'
WHEN SUM(c.delivered) > 0 THEN 'B'
WHEN SUM(c.submitted) > 0 THEN 'C'
ELSE 'No Match'
END AS X
FROM (the query above) as c
GROUP BY c.Customer_name
ORDER BY c.Customer_name;
Substituting Step 1 into Step 2 we get the actual query:
SELECT
c.Customer_name,
-- SUM(c.Is_delivered),
-- SUM(c.Is_submitted),
-- count(*),
CASE WHEN SUM(c.delivered) = count(*) THEN 'A'
WHEN SUM(c.delivered) > 0 THEN 'B'
WHEN SUM(c.submitted) > 0 THEN 'C'
ELSE 'No Match'
END AS X
FROM (
SELECT *,
CASE WHEN status = 'SUBMITTED' THEN 1 ELSE 0 END AS submitted,
CASE WHEN status = 'DELIVERED' THEN 1 ELSE 0 END AS delivered
FROM Customer_order
) as c
GROUP BY c.Customer_name
ORDER BY c.Customer_name;
Try it here:
https://www.db-fiddle.com/f/mSdREEgU1mT1pvczG2kZgm/1
You appear to be trying to count true comparions; unlike some other languages, in SQL a true value is not the same as 1 and a false value is not 0 so you need to use a CASE expression to convert the comparison to something that can be summed (or counted).
In this case, you can use conditional aggregation:
SELECT Customer_name,
CASE
WHEN COUNT(CASE status WHEN 'DELIVERED' THEN 1 END) = COUNT(status)
THEN 'A'
WHEN COUNT(CASE status WHEN 'DELIVERED' THEN 1 END) > 0
THEN 'B'
WHEN COUNT(CASE status WHEN 'SUBMITTED' THEN 1 END) > 0
THEN 'C'
ELSE 'No Match'
END AS Match
FROM Customer_Order
group by Customer_name
order by Customer_name;

Unexpected NULL in multi-column correlated update

I want to run a multi-column correlated update of this kind:
UPDATE t1 t1_alias
SET (table_name, tablespace_name) = (
SELECT table_name, tablespace_name
FROM t2 t2_alias
WHERE t1_alias.table_name = t2_alias.table_name
);
But my attempt:
update customer up
set (customer_name, account, active) = (
select tmp.name, tmp.account, case when tmp.active = 'Yes' then 1 else 0 end
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
);
... throws:
ORA-01407: cannot update ("FOO"."CUSTOMER"."CUSTOMER_NAME") to NULL
The source table customer_temp has no null values so I must be getting matches wrong. What is my error or misconception?
Presumably, there are some rows in the target table that have no match in the subquery.
You can avoid this with by adding an exists condition that filters out "unmatched" rows:
update customer up
set (customer_name, account, active) = (
select tmp.name, tmp.account, case when tmp.active = 'Yes' then 1 else 0 end
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
)
where exists (
select 1
from customer_temp tmp
where up.agent = substr(tmp.agent, -4) and up.customer_code = tmp.code
);

define multiple variables in select query in oracle

Getting error.. unable to define 2 parameters in one query
define price = 99.969000
define isin = '9128283C2';
WITH A AS
(select BUY_SELL,CASE WHEN BUY_SELL = 0 THEN (&price - 0.0025) ELSE (&price + 0.0025) END BS,PRODUCT_ISIN,QUANTITY
from table1 t where t.t_dt = '01-nov-17'
AND BUY_SELL = 0
AND quantity = 25 and product_isin = &isin)
SELECT * FROM A where row_num = 1;

Oracle Conditional Index with two identifiers

Is it possible to create a conditional index on two columns?
CREATE UNIQUE INDEX idx_dup_wfc
ON WF_WORKFLOW_CLASS (CASE WHEN is_active = 1
THEN (NAME, DEPT_OWNER)
ELSE NULL
END)
returns ORA-00906: missing left parenthesis however the following works
CREATE UNIQUE INDEX idx_dup_wfc
ON WF_WORKFLOW_CLASS (CASE WHEN is_active = 1
THEN NAME
ELSE NULL
END)
Yes, but you have to perform a CASE per column:
CREATE UNIQUE INDEX idx_dup_wfc
ON WF_WORKFLOW_CLASS
(CASE WHEN is_active = 1 THEN NAME END
,CASE WHEN is_active = 1 THEN DEPT_OWNER END
)
(The ELSE in your code is superfluous).

If statement within Where clause

I am working with a query which contains "IF" statements within a "WHERE" clause. But PL\SQL Developer is giving some errors while executing it. Can anyone please help me with the correct query? Here is the query:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE IF status_flag = STATUS_ACTIVE then t.status = 'A'
IF status_flag = STATUS_INACTIVE then t.status = 'T'
IF source_flag = SOURCE_FUNCTION then t.business_unit = 'production'
IF source_flag = SOURCE_USER then t.business_unit = 'users'
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;
I receive the error "ORA-00920: invalid relational operator".
Placing brackets around status_flag = STATUS_ACTIVE results in error "ORA-00907: missing right parenthesis"
CASE might help you out:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE t.status = (CASE WHEN status_flag = STATUS_ACTIVE THEN 'A'
WHEN status_flag = STATUS_INACTIVE THEN 'T'
ELSE null END)
AND t.business_unit = (CASE WHEN source_flag = SOURCE_FUNCTION THEN 'production'
WHEN source_flag = SOURCE_USER THEN 'users'
ELSE null END)
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;
The CASE statement evaluates multiple conditions to produce a single value. So, in the first usage, I check the value of status_flag, returning 'A', 'T' or null depending on what it's value is, and compare that to t.status. I do the same for the business_unit column with a second CASE statement.
You can't use IF like that. You can do what you want with AND and OR:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE ((status_flag = STATUS_ACTIVE AND t.status = 'A')
OR (status_flag = STATUS_INACTIVE AND t.status = 'T')
OR (source_flag = SOURCE_FUNCTION AND t.business_unit = 'production')
OR (source_flag = SOURCE_USER AND t.business_unit = 'users'))
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;

Resources