Sql statement for mutually exclusive events - sql

I am trying to run an sql statement on an iSeries that will output retuls based on a type parameter I pass in.
Just say mytable has a field called field1. field1 contains Y,N and NULL values.
A type of 'Y' should return just 'Y' values.
A type of 'N' should return not 'Y' values. (ie. Null, N and any other junk in the field)
I tried this...
select *
from mytable
where field1 in case when :type = 'Y' then 'Y'
else (select field1 from mytable where field1 <> 'Y') end
However, this does not work.

I believe the logic you are looking for is this:
SELECT *
FROM myTable
WHERE (:type = 'Y' AND field1 IS NOT null AND field1 = 'Y')
OR (:type <> 'Y' AND (field1 IS null OR field1 <> 'Y'))
(keep in mind the fact that short-circuit logic is not garuanteed with SQL...)
Remember that null doesn't really compare to anything, and it's best to call out the fact that you actually want it (in the second case).

Related

Column is null using Case When SQL

I'm using SQL Developer
I need to accept a user input as either Y or N.
If N is entered, I need to convert this to null. If Y is entered it should remain Y. The script then needs to search for a column with either a null value or a value of Y depending on what is entered by the user.
I have the code below with a decent idea for how to tackle it
accept WITHDRAWN char prompt 'Please enter Y or N)'
SELECT *
FROM table1
WHERE column1 = case when '&WITHDRAWN' = 'N' then null else '&WITHDRAWN' end;
As you can probably tell, it doesn't work, as for the column to be null, the '=' sign would need to be an 'is'. Likewise for the column to be 'Y' then the sign would need to be '='.
I really can't figure out a way to substitute N for the value of null and allow column1 to match up to this. Is it even possible?
I'd coalesce the column1 value so when it's Null, N is substituted and compared to the user input.
SELECT *
FROM table1
WHERE coalsece(column1,'N') = &WITHDRAWN;
Assumption being in table1 all column1's that are null are infact 'N' so the coalesce simply allows us to do a character to character comparison.
Also be aware that indexes on column1 will be ignored since we had to use a function to get the 'N' value returned.
You don't need case at all:
SELECT *
FROM Table1
WHERE
(
'&WITHDRAWN' = 'N'
AND Column1 IS NULL
)
OR Column1 = 'Y'
select * from table1
where (
(column1 = '&WITHDRAWN' and '&WITHDRAWN' != 'N')
or
(column1 is null and '&WITHDRAWN' = 'N'))
Hope this help!
SELECT * FROM table1
WHERE (
(column1 = '&&WITHDRAWN' AND '&&WITHDRAWN' = 'Y')
OR
(column1 IS NULL AND '&&WITHDRAWN' = 'N'))

CASE STRUCTURE IN A DB2 SQL UPDATE

I need to update a value (FIELD_E) in one table based on the value in a field of a second table as long as certain conditions are met. Here is what I am working with thus far.
TABLE_1.FIELD_C is a primary key
TABLE_2.FIELD_D is a foreign key
There is a ONE TO MANY relationship between TABLE_1.FIELD_C AND TABLE_2.FIELD_D
UPDATE TABLE_1
SET TABLE_1.FIELD_E = (
CASE
WHEN
(
SELECT MAX(FIELD_A)
FROM TABLE_1,
TABLE_2
WHERE TABLE_1.FIELD_C = TABLE_2.FIELD_D
AND TABLE_1.FIELD_A IS NOT NULL
AND TABLE_2.FIELD_B IS NULL) = 'Y' THEN '1'
WHEN
(
SELECT MAX(FIELD_A)
FROM TABLE_1,
TABLE_2
WHERE TABLE_1.FIELD_C = TABLE_2.FIELD_D
AND TABLE_1.FIELD_A IS NOT NULL
AND TABLE_2.FIELD_B IS NULL) = 'N' THEN '10'
WHEN
(
SELECT MAX(FIELD_A)
FROM TABLE_1,
TABLE_2
WHERE TABLE_1.FIELD_C = TABLE_2.FIELD_D
AND TABLE_1.FIELD_A IS NOT NULL
AND TABLE_2.FIELD_B IS NULL) = 'U' THEN '9'
ELSE NULL
END
WHERE TABLE_1.FIELD_C = TABLE_2.FIELD_D
AND TABLE_1.FIELD_A IS NOT NULL
AND TABLE_2.FIELD_B IS NULL
I know I could probably do this more simply by just taking a snapshot and writing multiple statements using primary keys but if the values were to change after the snapshot and before the update, an incorrect update could be made.
Can I get some suggestions on how to do this using a similar case structures statement?
Your query is doing several things you likely do not intend, besides the blatant syntax and construction errors. Making some assumptions about reasonable behavior, the query can be a lot simpler than your current effort:
UPDATE Table_1 SET field_e = CASE field_a WHEN 'Y' THEN '1'
WHEN 'N' THEN '10'
WHEN 'U' THEN '9'
ELSE null END
WHERE field_a IS NOT NULL
AND EXISTS (SELECT '1'
FROM Table_2
WHERE Table_2.field_d = Table_1.field_c
AND Table_2.field_b IS NULL)
SQL Fiddle Example
Your original query had the following behavior or other problems:
Your subqueries were certainly returning more than one row (error)
Your outermost SELECT mentions Table_2 without providing a reference (error)
There was no correlation between the outer UPDATE and any of the subqueries, meaning everything would be updated to have 1, regardless of the actual contents of a particular row's field.
I'm also not sure if you want the ELSE NULL in your CASE - this has the effect of erasing whatever value is currently in field_e if field_a doesn't have a matching value. Or rather, not restricting the update to those rows containing the values interested in (because ELSE null is implied if excluded).

Case when statement in SQL

I am using the following query. In this query I want to apply the where clause based on passed parameter. But the issue is that where clause is like 'value = if parameterVal = 'I' than NULL else NOT NULL'
I've build a query like this
SELECT * FROM MASTER
WHERE
Column1 IS (CASE WHEN :Filter = 'I' THEN 'NULL' ELSE 'NOT NULL' END)
but it's not working. Help me solve this.
UPDATE
Updating question to elaborate question more clearly.
I've one table MASTER. Now I am passing one parameter in query that is Filter (indicated by :Filter in query).
Now when the Filter parameter's value is 'I' than it should return the following result.
SELECT * FROM MASTER WHERE Column1 IS NULL
but if the passed argument is not equal to 'I' than,
SELECT * FROM MASTER WHERE Column1 IS NOT NULL
SELECT * FROM MASTER
WHERE (Filter = 'I' AND Column1 IS NULL)
OR
(Filter <> 'I' AND Column1 IS NOT NULL)
If you really insist on using a CASE the SELECT could be rewritten as:
SELECT *
FROM MASTER
WHERE CASE
WHEN COLUMN1 IS NULL AND FILTER = 'I' THEN 1
WHEN COLUMN1 IS NOT NULL AND FILTER <> 'I' THEN 1
ELSE 0
END = 1
SQLFiddle here
Frankly, though, I think that this is very difficult to interpret, and I suggest that #MAli's version is better.
Your case has assignment not equality check

CASE in WHERE expression using IN clause

I need that when var1 is equal to 'Y' the query show the result of the table with the column = 'Y', but when var1 = 'N' the result should be the data with column with 'Y' and 'N'.
I need to put it in a where clause, cause I'm using oracle forms.
I tried this way but the query didn't show any result:
SELECT *
FROM table
WHERE column1 IN ((CASE WHEN var1 = 'Y' THEN q'[('Y')]'
ELSE TO_CHAR(q'[('Y','N')]')
END))
Can you help me? Thank you.
There is no need for CASE logic here, as you can fit this into a regular WHERE clause with boolean logic, wrapping each condition (var1 = 'Y', var1 <> 'Y') in a () group.
SELECT *
FROM table
WHERE
(var1 = 'Y' AND column1 = 'Y')
OR (var1 <> 'Y' AND column1 IN ('Y','N'))
Note, I used var1 <> 'Y' here to emulate your ELSE case, but if it is only two possible values Y/N you may use var1 = 'N' for clarity.
WHERE
(var1 = 'Y' AND column1 = 'Y')
OR (var1 = 'N' AND column1 IN ('Y','N'))
Actually, if Y/N are the only possible values for column1, then it could be simplified to:
WHERE
(var1 = 'Y' AND column1 = 'Y')
-- Returns all rows for column1 if Y,N are the only possible values
-- No need to explicitly filter it
OR (var1 <> 'Y')

Show field dependent on whether other field contains data

Is it possible in an SQL query to only show a field if another field has data? For example, if Field1 <> '', then show the value in Field2 else don't show the value?
It can be done using a case statement. (At least in SQL Server)
select case when Field1 <> ''
then Field2
end as Field2
from YourTable
Sure (this works in Oracle and SQLite):
select
field1,
(case
when field1 is null then null
else field2
end) field2_wrapped
from my_table
if 'has no data' means the empty string (''), you need to use this statement:
SELECT Filed2 FROM Table1 WHERE Filed1<>''
If 'no data' means NULL value, you need use
SELECT Filed2 FROM Table1 WHERE NOT (Filed2 IS NULL)
Take a look at Standard SQL functions COALESCE() and NULLIF():
COALESCE(NULLIF(Field1, ''), Field2)