So I have an sql query i am currently working on that is like this:
SELECT * from tableA where
( status = NVL('','OPEN') or status = NVL('','CLOSED') )
and delete_flag != 'Y'
The above query works fine and gives me the result I want.. but I was wondering if there is anyway I can combine the above status IN NVL line to one instead of using the or there.
for example, I want to be able to do:
SELECT * from tableA where
status IN NVL('','OPEN','CLOSED')
and delete_flag != 'Y'
But the apostrophes are not working with me here.. how can I work around it?
You are getting an input parameter from your application that can have the values "Open", "Closed" or null
You want to be able to select status values that equal this input paremeter if it is null or the value of the input if it isn't.
To have null for a filter default to all you use COALESCE and the column you are filtering on.
Like this
SELECT * from tableA
where COALESCE(parameter,status) = status
and status in ('OPEN','CLOSED') -- see comments
and delete_flag != 'Y'
In this case if parameter is OPEN you will get all OPEN items, if parameter is CLOSED you will get all closed items and if it is null you will get all items.
This is a very common pattern in web applications.
Single line version
SELECT * from tableA
where COALESCE(parameter,CASE WHEN status in ('OPEN','CLOSED') then status ELSE '' END) = status
and delete_flag != 'Y'
simply:
SELECT * from tableA
where 1=1
and nvl(status, '---') IN ('OPEN','CLOSED')
and delete_flag != 'Y'
In Oracle an empty string '' is equivalent to NULL.
So NVL( '', 'OPEN' ) is the equivalent to NVL( NULL, 'OPEN' ) which can be simplified to just 'OPEN'.
So your query is:
SELECT *
FROM tableA
WHERE ( status = 'OPEN' OR status = 'CLOSED' )
AND delete_flag != 'Y'
Which can be simplified to:
SELECT *
FROM tableA
WHERE status IN ( 'OPEN', 'CLOSED' )
AND delete_flag != 'Y'
You can implement a dynamic list of options using a collection:
CREATE TYPE stringlist IS TABLE OF VARCHAR2(100);
/
SELECT a.*
FROM tableA a
INNER JOIN
( SELECT stringlist( 'OPEN', 'CLOSED' ) AS options FROM DUAL ) o
ON ( o.options IS EMPTY OR a.status MEMBER OF o.options )
WHERE a.delete_flag <> 'Y'
Related
Example field name status have 3 fix values in there rows, now I want first 'Pending' values then 'Approved' and then 'Rejected' values in row.
I tried this query
qry = "SELECT * FROM Table_Name ORDER BY status dsc"
Use case or iif in your order by clause:
SELECT * -- Better specify column names here
FROM Table_Name
ORDER BY IIF([status] = 'Pending', 0, 1), IIF([status] = 'Approved', 0, 1), [status];
If there's a large list of values that you want to apply a specific order, you better add a numeric column that specifies this order:
SELECT * -- Better specify column names here
FROM Table_Name
ORDER OrderByColumn;
You can use CASE WHEN SYNTAX
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
WHEN conditionN THEN resultN
ELSE result
END
In your case, I suggest to use this SQL Query:
SELECT * FROM Table_Name ORDER BY
(CASE
WHEN status = 'Pending' THEN 0
WHEN status = 'Approved' THEN 1
ELSE 2
END) dsc
i solved this problem in sql using condition in order by area
example
SELECT * FROM Table_Name ORDER BY CASE WHEN status = 'Pending' THEN '1' WHEN status = 'Approved' THEN '2' WHEN status = 'Rejected' THEN '3' ELSE status END ASC
I have a huge query and I am wondering if it is in Oracle possible
to get the result of a case-when-statement and use it for comparison? My CASE-STATEMENT is declared in the Select-Statement and it looks like this.
SELECT........
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST;
Now I want to get the result of this case-statement and use it in the where part? Is it possible? (Sry this may be a dumb question)
If you define your CASE statement in either an inline-view or a common table expression (aka WITH clause), you can refer to it by whatever alias you give it.
For example (inline-view):
SELECT ...
FROM ( SELECT .....
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST
FROM...
) v
WHERE v.test = 'TEST2';
As a common table expression, it would be:
WITH cte AS ( SELECT........
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST
FROM ... )
SELECT ...
FROM cte
WHERE test = 'TEST2';
You can use a case statement in the where clause, for eg.:
select * from table
where table.field = (CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END)
This will compare the value returned from the case statement with the table field.
I have a query like the below showed.
select * from tbl a
WHERE a.device_cat =
(CASE (SELECT :VIEW1
FROM DUAL
WHERE :VIEW1 IN
(SELECT DISTINCT version
FROM tbl2))
WHEN NULL
THEN
NULL
ELSE
DECODE (:device_cat, 'ALL', a.device_cat, :device_cat)
END)
So, when the below query is null, a.device_cat should be null, if so, the above query will always return empty records. But, the records are definitely exists when a.device_cat is null. Please help me! Thanks!
(SELECT :VIEW1
FROM DUAL
WHERE :VIEW1 IN
(SELECT DISTINCT version
FROM tbl2)
You cannot compare to null like this:
a.device_cat =null
Try this:
select * from tbl a
WHERE nvl(a.device_cat, 0) =
nvl((CASE (SELECT :VIEW1
FROM DUAL
WHERE :VIEW1 IN
(SELECT DISTINCT version
FROM tbl2))
WHEN null
THEN
null
ELSE
DECODE (:device_cat, 'ALL', a.device_cat, :device_cat)
END), 0)
You cannot compare null to null like that.
It is like:
undefined = undefined
Which is not true... Something you don't know isn't something you don't know. At least, in SQL.
You can use coalesce to circumvent this:
WHERE coalesce(a.device_cat, '###') =
(CASE (SELECT coalesce(:VIEW1, '###')
The WHEN NULL case will never be reached, because in SQL NULLs are not equal to each other.
Switching to the other CASE syntax should work, though:
CASE
WHEN (
SELECT :VIEW1 FROM DUAL WHERE :VIEW1 IN (SELECT DISTINCT version FROM tbl2)
) IS NULL
THEN NULL
ELSE DECODE (:device_cat, 'ALL', a.device_cat, :device_cat)
END
This expression uses IS NULL operator instead of the comparison, providing the desired behavior.
I have a query that contains a WHERE clause with a CASE statement in it (See code below), somehow it doesn't seem to work.
select * FROM
details
where orgcode in
(case when orgtype='P' then
(SELECT distinct [PCode]
FROM [GPOS_Extract].[dbo].[GP8288List])
else
0 end )
How about
select * FROM details
where (orgtype <> 'P' AND orgcode = 0)
or orgcode in
(
SELECT distinct [PCode]
FROM [GPOS_Extract].[dbo].[GP8288List]
)
Or try this:
SELECT * FROM details
WHERE details.orgcode IN
( SELECT DISTINCT
(CASE WHEN details.orgtype='P'
THEN [GPOS_Extract].[dbo].[GP8288List].PCode
ELSE 0 END)
FROM [GPOS_Extract].[dbo].[GP8288List] )
I think the following is the logic that is equivalent to your attempt:
select *
FROM details
where (orgtype = 'P' and
orgcode in (SELECT distinct [PCode]
FROM [GPOS_Extract].[dbo].[GP8288List]
)
) or
((orgtype <> 'P' or orgtype is NULL) and orgcode = 0);
what about this,
select a.*,case when orgtype='P' then PCode else '0' end FROM
details a
left join [GPOS_Extract].[dbo].[GP8288List] b on a.orgcode=b.PCode
case returns a single value. You are trying to use it as though it returns a result set. What you want is:
select * FROM details d
where (orgtype = 'p'
And exists (Select *
From GPOS_Extract.dbo.GP8288List
Where PCode = d.orgcode))
or (orgtype <> 'p' And orgcode= 0)
I would like to know if there is a better way of writing the SELECT clause in the query below. There are three possible cases for status. It can either have a value of 'A' or 'N' or null.
I think that placing the AND status = 'A' in the where clause is redundant when you are comparing the subTable values to a value of 'A'. Is there any way that this could be rewritten more efficiently? I feel like restricting the status in the WHERE clause is always going to give you an 'A' and hence pointless to do the CASE statement.
ALTER VIEW dbo.st_review_status_vw AS
(
SELECT c.st_id, c.ms_price_comp_fy,
CASE
WHEN (SELECT status FROM
(SELECT st_id, status, ms_price_comp_fy
FROM ms_price_comp
WHERE st_id = c.st_id
AND ms_price_comp_fy = c.ms_price_comp_fy
AND status = 'A'
GROUP BY st_id, status, ms_price_comp_fy)
AS subTable) = 'A' THEN 'C'
ELSE 'I'
END AS status,
MAX(date_approved) AS date_completed
FROM ms_price_comp AS c
GROUP BY c.st_id, c.ms_price_comp_fy
)
try this
ALTER VIEW dbo.st_review_status_vw AS (
SELECT c.st_id, c.ms_price_comp_fy,
CASE WHEN MIN(status) = 'A' THEN 'C'
ELSE 'I'
END AS status,
MAX(date_approved) AS date_completed
FROM ms_price_comp AS c
GROUP BY c.st_id, c.ms_price_comp_fy
)
This looks to be the same to me
ALTER VIEW dbo.st_review_status_vw AS (
SELECT
c.st_id
, c.ms_price_comp_fy
, CASE
WHEN MIN(status) = 'A' THEN 'C'
ELSE 'I'
END AS status
, MAX(date_approved) AS date_completed
FROM ms_price_comp AS c
GROUP BY c.st_id, c.ms_price_comp_fy
)