Is it possible to write an optimized version of this oracle query so that it does not execute 10 times?
Thanks in advance for your help.
select async, column1 from
(
select distinct async, COLUMN1 from Table1
where COLUMN1 is not null
union
select distinct async, COLUMN2 as COLUMN1 from Table1 and
where COLUMN1 is null and COLUMN2 is not null
union
select distinct async, COLUMN3 as COLUMN1 from Table1
where COLUMN1 is null and COLUMN2 is null and COLUMN3 is not null
union
select distinct async, COLUMN4 as COLUMN1 from Table1
where COLUMN1 is null and COLUMN2 is null and COLUMN3 is null and
COLUMN4 is not null
union
select distinct async, COLUMN5 as COLUMN1 from Table1
where COLUMN1 is null and COLUMN2 is null and COLUMN3 is null and
COLUMN4 is null and COLUMN5 is not null
union
select distinct async, COLUMN6 as COLUMN1 from Table1
where COLUMN1 is null and COLUMN2 is null and COLUMN3 is null and
COLUMN4 is null and COLUMN5 is null and
COLUMN6 is not null
union
select distinct async, COLUMN7 as COLUMN1 from Table1
where COLUMN1 is null and COLUMN2 is null and COLUMN3 is null and
COLUMN4 is null and COLUMN5 is null and COLUMN6 is null and
COLUMN7 is not null
union
select distinct async, COLUMN8 as COLUMN1 from Table1
where
COLUMN1 is null and COLUMN2 is null and COLUMN3 is null and
COLUMN4 is null and COLUMN5 is null and COLUMN6 is null and
COLUMN7 is null and COLUMN8 is not null
union
select distinct async, COLUMN9 as COLUMN1 from Table1
where
COLUMN1 is null and COLUMN2 is null and COLUMN3 is null and
COLUMN4 is null and COLUMN5 is null and COLUMN6 is null and
COLUMN7 is null and COLUMN8 is null and COLUMN9 is not null
union
select distinct async, COLUMN10 as COLUMN1 from Table1
where COLUMN1 is null and COLUMN2 is null and
COLUMN3 is null and COLUMN4 is null and COLUMN5 is null and
COLUMN6 is null and COLUMN7 is null and COLUMN8 is null and
COLUMN9 is null and COLUMN10 is not null
)
COALESCE does the trick, it selects the first NOT NULL value
select DISTINCT async, coalesce(column1,column2,column3,column4,...) from Table1;
Related
I am having table as below
And I want output as below
I tried doing something as below
SELECT * FROM TABLE_NAME WHERE COLUMN2 = 'PQR' AND COLUMN3 IS NOT NULL
But it also removes 3rd and 4th row from 1st table. Whereas in output of the query I need to remove only rows which are having Column2 as PQR and Column3 as NOT NULL
I also tried to use case statements but I'm not able to get actual idea of how to implement it.
EDIT 1:-
Also I thought of trying one more thing now.
SELECT * FROM TABLE_NAME WHERE COLUMN2 IN ('PQR', 'XYZ', 'RST') AND COLUMN3 IS NOT NULL
But the problem is in actual table COLUMN2 is having more than 150 distinct values which I can't go on mentioning in IN clause.
not(COLUMN2 = 'PQR' AND COLUMN3 IS NOT NULL)
Example:
SQL> ;
1 with -- test data:
2 t(column1,column2,column3) as (
3 select 'ABC','PQR',cast(null as int) from dual union all
4 select 'DEF','PQR',123 from dual union all
5 select 'GHI','XYZ',cast(null as int) from dual union all
6 select 'JKL','RST',cast(null as int) from dual
7 ) -- test query:
8 select *
9 from t
10* where not(COLUMN2 = 'PQR' AND COLUMN3 IS NOT NULL)
SQL> /
COL COL COLUMN3
--- --- ----------
ABC PQR NULL
GHI XYZ NULL
JKL RST NULL
or lnnvl(COLUMN2 = 'PQR') or COLUMN3 IS NULL
Example:
with -- test data:
t(column1,column2,column3) as (
select 'ABC','PQR',cast(null as int) from dual union all
select 'DEF','PQR',123 from dual union all
select 'GHI','XYZ',cast(null as int) from dual union all
select 'JKL','RST',cast(null as int) from dual
) -- test query:
select *
from t
where lnnvl(COLUMN2 = 'PQR') or COLUMN3 IS NULL;
COL COL COLUMN3
--- --- ----------
ABC PQR NULL
GHI XYZ NULL
JKL RST NULL
What you want is (if I understood correctly)
NOT (COLUMN2 = 'PQR' AND COLUMN3 IS NOT NULL)
which is equivalent to
COLUMN2!='PQR' OR COLUMN3 IS NULL
I am new to oracle and below is my SQL.
SELECT * FROM TABLE1 WHERE COLUMN1 = 'YES'
AND COLUMN2 IN (
CASE WHEN EXISTS(SELECT * FROM TABLE1 WHERE COLUMN1 = 'YES' AND COLUMN2 NOT LIKE '%NO%')
THEN
SELECT COLUMN2 FROM TABLE1 WHERE COLUMN1 = 'YES' AND COLUMN2 NOT LIKE '%YES%'
ELSE
SELECT COLUMN2 FROM TABLE1 WHERE COLUMN1 = 'YES' AND COLUMN2 NOT LIKE '%YES%' END)
it is giving ORA-00936: missing expression at then statement. What am I doing wrong?
The subqueries after THEN and ELSE must be enclosed inside parentheses:
SELECT * FROM TABLE1 WHERE COLUMN1 = 'YES'
AND COLUMN2 IN (
CASE
WHEN EXISTS (SELECT * FROM TABLE1 WHERE COLUMN1 = 'YES' AND COLUMN2 NOT LIKE '%NO%')
THEN (SELECT COLUMN2 FROM TABLE1 WHERE COLUMN1 = 'YES' AND COLUMN2 NOT LIKE '%YES%')
ELSE (SELECT COLUMN2 FROM TABLE1 WHERE COLUMN1 = 'YES' AND COLUMN2 NOT LIKE '%YES%')
END
)
This will work only if these subqueries don't return more than 1 row.
Also, both subqueries are the same. Is this a typo?
And IN can be changed to = since CASE returns only 1 value.
I have a number of tables that mix 'real' values with nulls in columns. From exerience, issuing a SELECT against these that looks like:
SELECT column1, column2, column3 FROM mytable WHERE column1 != 'a value';
...doesn't return the records I expect. In the current table I am working on, this returns an empty recordset, even though I know I have records in the table with NULLs in column1, and other records in the table that have the value I am "!="ing in column1. I am expecting, in this case, to see the records with NULLs in column1 (and, of course, anything else if there were other not 'a value' values in column1.
Experimenting with NVL in the WHERE clause doesn't seem to give me anything different:
SELECT column1, column2, column3 FROM mytable WHERE NVL(column1, '') != 'a value';
...is also returning an empty recordset.
Using 'IS NULL' will technically give me the correct recordset in my current example, but of course if any records change to something like 'another value' in column1, then IS NULL will exclude those.
NULL can't be compared in the same way that other values can be. You must use IS NULL. If you want to include NULL values, add an OR to the WHERE clause:
SELECT column1, column2, column3 FROM mytable WHERE column1 != 'a value' OR column1 IS NULL
The query doesn't work because SQL handles equality checks (!=) different from checking if null (IS NULL).
What you could do here is something like:
SELECT column1, column2, column3
FROM mytable
WHERE column1 != 'a value' OR column1 is null;
See Not equal <> != operator on NULL.
What you were trying was correct. You just need change it a little. see below-
SELECT column1, column2, column3 FROM mytable WHERE NVL(column1, '0') != 'a value';
Instead of empty string, pass any character in NVL's second argument.
"Experimenting with NVL in the WHERE clause doesn't seem to give me anything different"
That's true:
SQL> select * from mytable;
COLUMN1 COLUMN2 COLUMN3
-------------------- ---------- ---------
a value 1 25-JUL-17
not a value 2 25-JUL-17
whatever 3 25-JUL-17
4 26-JUL-17
SQL> SELECT column1, column2, column3 FROM mytable WHERE NVL(column1, '') != 'a value';
COLUMN1 COLUMN2 COLUMN3
-------------------- ---------- ---------
not a value 2 25-JUL-17
whatever 3 25-JUL-17
SQL>
This is because your experiment didn't go far enough. For historical reasons Oracle treats an empty string as null so your nvl() statement effectively just subs one null for another. But if you had used a proper value in your call you would have got the result you wanted:
SQL> SELECT column1, column2, column3 FROM mytable WHERE NVL(column1, 'meh') != 'a value';
COLUMN1 COLUMN2 COLUMN3
-------------------- ---------- ---------
not a value 2 25-JUL-17
whatever 3 25-JUL-17
4 26-JUL-17
SQL>
The alternative approach is to explicitly test for NULL and test for the excluding value...
SQL> SELECT column1, column2, column3 FROM mytable
2 where column1 is null or column1 != 'a value';
COLUMN1 COLUMN2 COLUMN3
-------------------- ---------- ---------
not a value 2 25-JUL-17
whatever 3 25-JUL-17
4 26-JUL-17
SQL>
The second approach is probably more orthodox.
1) Undocumented Oracle function SYS_OP_MAP_NONNULL. (It exists from oracle10)
with abc as ( select 'a value' as col1 from dual
union all
select '' as col1 from dual)
select * from abc
where SYS_OP_MAP_NONNULL(col1) != SYS_OP_MAP_NONNULL('a value')
;
2) LNNVL - Check table in the documentation for clarification.
with abc as ( select 'a value' as col1 from dual
union all
select '' as col1 from dual)
select * from abc
where lnnvl( col1 = 'a value');
;
is there any way to reorder columns in a table (or query) based on value.
for example, on every row, FacName should be first, NPI - 2nd, TIN - 3rd and Address - 4th.
thank you!
select col1, col2, col3, col4 from (
select * from (
select
n, str, row_number() over (partition by n order by
decode(substr(str,1,3),'Fac',1,'NPI',2,'TIN',3,'Add',4)) cn
from (
select * from (select t.*, rownum n from t)
unpivot (str for cn in (col1 as 0, col2 as 0, col3 as 0, col4 as 0))
)
)
pivot (min(str) for cn in (1 as col1, 2 as col2, 3 as col3, 4 as col4))
)
order by n
fiddle
The fact that you want to move data between columns strongly implies that the underlying data model is broken and needs to be normalized. Fixing the data model would be much more appropriate than adding another layer of complexity to the system.
That being said, you should be able to do something like
SELECT (CASE WHEN column1 LIKE 'FacilityName%' THEN column1
WHEN column2 LIKE 'FacilityName%' THEN column2
WHEN column3 LIKE 'FacilityName%' THEN column3
WHEN column4 LIKE 'FacilityName%' THEN column4
ELSE null
END) column1,
(CASE WHEN column1 LIKE 'NPI%' THEN column1
WHEN column2 LIKE 'NPI%' THEN column2
WHEN column3 LIKE 'NPI%' THEN column3
WHEN column4 LIKE 'NPI%' THEN column4
ELSE null
END) column2,
(CASE WHEN column1 LIKE 'TIN%' THEN column1
WHEN column2 LIKE 'TIN%' THEN column2
WHEN column3 LIKE 'TIN%' THEN column3
WHEN column4 LIKE 'TIN%' THEN column4
ELSE null
END) column3,
(CASE WHEN column1 LIKE 'Address%' THEN column1
WHEN column2 LIKE 'Address%' THEN column2
WHEN column3 LIKE 'Address%' THEN column3
WHEN column4 LIKE 'Address%' THEN column4
ELSE null
END) column4
FROM( <<your query>> )
I have the following query:
SELECT COLUMN1, COLUMN2, COUNT(*)
FROM TABLE
WHERE COLUMN3 IS NOT NULL
AND COLUMN4 = 1
AND COLUMN5 = 4
AND COLUMN6 = 43
AND COLUMN7 = $P{YEAR}
AND COLUMN8 = $P{IT}
GROUP BY COLUMN1, COLUMN2
ORDER BY COLUMN1 ASC
I wonder if it is possible to do something like:
SELECT COLUMN1, COLUMN2, COUNT(*)
FROM TABLE
WHERE COLUMN3 IS NOT NULL
AND COLUMN4 = 1
AND COLUMN5 = 4
AND COLUMN6 = 43
AND COLUMN7 = $P{YEAR}
IF ($P{IT} != 'ALL') { AND COLUMN8 = $P{IT} }
GROUP BY COLUMN1, COLUMN2
ORDER BY COLUMN1 ASC
In other words, I want to add to the where clause "AND COLUMN8 = $P{IT}" only if "$P{IT}" value is not "ALL". This means if the report must filter by the column "COLUMN8" or not.
Do someone know if this is possible? Is there other approach that accomplish the work?
I tried to execute the above query but I got a 'Compilation running time'.
Thanks in advance.
Yes, you can do that in iReport. But you need to look at it slightly differently. You need a second parameter. Keep $P{IT}, and add $P{IT_SQL}. Give $P{IT_SQL} a default value like this:
$P{IT}.equals("ALL") ? "" : " AND COLUMN8 = '" + $P{IT} + "'"
Then your query should look like this:
SELECT COLUMN1, COLUMN2, COUNT(*)
FROM TABLE
WHERE COLUMN3 IS NOT NULL
AND COLUMN4 = 1
AND COLUMN5 = 4
AND COLUMN6 = 43
AND COLUMN7 = $P{YEAR}
$P!{IT_SQL}
GROUP BY COLUMN1, COLUMN2
ORDER BY COLUMN1 ASC
That will give you the desired SQL (none!) when $P{IT} has the value "ALL", and it will give you the desired SQL (COLUMN8 = 'abc') when $P{IT} has the value "abc".