Multiple select for aleady joined table - oracle

Below is a part of my select query. In the same query I am selecting COLUMN_1 from a table TABLE2 with condition check. Also I am joining this table at end with one of the condition in the inner select as below. Can we have any other way to handle this situation with out using multiple `SELECT inside.
SELECT
T1.COLUMN_1
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='A' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_2
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='B' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_3
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='C' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_4
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='D' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_5
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='E' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_6
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='F' AND COLUMN_11=T2.COLUMN_11)
FROM TABLE1 T1, TABLE2 T2
-- plus two more tables
--plus some other conditions
WHERE T1.COLUMN_11=T2.COLUMN_11

Use CASE instead:
SELECT T1.COLUMN_1
,CASE
WHEN T2.COLUMN_22 = 'A'
THEN T2.COLUMN_1
END
,T1.COLUMN_2
,CASE
WHEN T2.COLUMN_22 = 'B'
THEN T2.COLUMN_1
END
,T1.COLUMN_3
,CASE
WHEN T2.COLUMN_22 = 'C'
THEN T2.COLUMN_1
END
,T1.COLUMN_4
,CASE
WHEN T2.COLUMN_22 = 'D'
THEN T2.COLUMN_1
END
,T1.COLUMN_5
,CASE
WHEN T2.COLUMN_22 = 'E'
THEN T2.COLUMN_1
END
,T1.COLUMN_6
,CASE
WHEN T2.COLUMN_22 = 'F'
THEN T2.COLUMN_1
END
FROM TABLE1 T1
INNER JOIN TABLE2 T2 ON T1.COLUMN_11 = T2.COLUMN_11;
EDIT
I changed the query to use the ansi join syntax. But that change is irrelevant to what you are asking. You can keep your join syntax if you want. The only relevant change is in the SELECT portion of the query.

You won't have very clean solutions I think. Another possibility is with an inner join by case:
SELECT
T1.COLUMN_1,
T2_1.COLUMN_1,
T1.COLUMN_2,
T2_2.COLUMN_1
T1.COLUMN_3,
T2_3.COLUMN_1
T1.COLUMN_4,
T2_4.COLUMN_1
T1.COLUMN_5,
T2_5.COLUMN_1
T1.COLUMN_6,
T2_6.COLUMN_1
FROM TABLE1 T1
INNER JOIN TABLE2 T2_1 ON T1.COLUMN_11=T2_1.COLUMN_11 AND T2_1.COLUMN_22 = 'A',
INNER JOIN TABLE2 T2_2 ON T1.COLUMN_11=T2_2.COLUMN_11 AND T2_2.COLUMN_22 = 'B',
INNER JOIN TABLE2 T2_3 ON T1.COLUMN_11=T2_3.COLUMN_11 AND T2_3.COLUMN_22 = 'C',
INNER JOIN TABLE2 T2_4 ON T1.COLUMN_11=T2_4.COLUMN_11 AND T2_4.COLUMN_22 = 'D',
INNER JOIN TABLE2 T2_5 ON T1.COLUMN_11=T2_5.COLUMN_11 AND T2_5.COLUMN_22 = 'E',
INNER JOIN TABLE2 T2_6 ON T1.COLUMN_11=T2_6.COLUMN_11 AND T2_6.COLUMN_22 = 'F',
WHERE
etc...

Related

Oracle Hierarchical queries: Translate START WITH ... CONNECT BY PRIOR into 'Recursive Subquery Factoring'

How would the following START WITH / CONNECT BY hierarchical query look like when translated into a RECURSIVE SUBQUERY FACTORING hierarchical query with WITH clause:
SELECT t1.id
FROM table1 t1, table2 t2
WHERE t1.version_id = t2.id
AND t1.baseline_date = TRIM (TO_DATE ('2015-05-26', 'yyyy-mm-dd'))
AND t2.entry_date = t1.baseline_date
START WITH t1.id IN (SELECT id
FROM table1
WHERE parent_id = 101015)
CONNECT BY PRIOR t1.id = t1.parent_id
ORDER SIBLINGS BY t1.child_index;
I think you want:
WITH rsqfc (id, child_index, baseline_date) AS (
SELECT t1.id,
t1.child_index,
t1.baseline_date
FROM table1 t1
INNER JOIN table2 t2
ON ( t1.version_id = t2.id
AND t2.entry_date = t1.baseline_date )
WHERE t1.parent_id = 101015
UNION ALL
SELECT t1.id,
t1.child_index,
t1.baseline_date
FROM rsqfc r
INNER JOIN table1 t1
ON (r.id = t1.parent_id)
INNER JOIN table2 t2
ON ( t1.version_id = t2.id
AND t2.entry_date = t1.baseline_date )
)
SEARCH DEPTH FIRST BY child_index SET order_id
SELECT id
FROM rsqfc
WHERE baseline_date = DATE '2015-05-26';
However, without sample data it is difficult to be sure.

Converting Oracle Query to Hive

How can I convert the below query in Oracle to Hive?
SELECT A.EMP_NO, A.LOGIN_TIMESTAMP FROM TABLE1 A, TABLE2 B
WHERE A.EMP_NO = 1234 AND B.EMP_CURR =
(SELECT MIN(EMP_CURR) FROM TABLE2 WHERE EMP_NO = A.EMP_NO AND
LOGIN_TIMESTAMP = A.LOGIN_TIMESTAMP AND EMP_STATUS_CODE <> 'P')
Use dense_rank() to get rows with minimum EMP_CURR:
SELECT A.EMP_NO, A.LOGIN_TIMESTAMP
FROM TABLE1 A
INNER JOIN (select B.*,
dense_rank() over(partition by B.EMP_NO, B.LOGIN_TIMESTAMP order by B.EMP_CURR) rn
from TABLE2 B where EMP_STATUS_CODE <> 'P'
) B
on B.EMP_NO = A.EMP_NO and B.LOGIN_TIMESTAMP = A.LOGIN_TIMESTAMP and B.rn=1
where B.rn=1 and A.EMP_NO = 1234;

Alternate approach for Case statement in oracle

I have a query insert statement like shown below
insert into my_table
select col1,col2,CASE
WHEN EXISTS
(SELECT 1 FROM Table_A m WHERE m.COLA='XXX' AND m.id=b.id
)
THEN
(SELECT m.COLB FROM Table_A m WHERE m.COLA='XXX' AND m.id=b.id
)
ELSE 'Not Open'
END XXX,
CASE
WHEN EXISTS
(SELECT 1 FROM Table_A m WHERE m.COLA='YYY' AND m.id=b.id
)
THEN
(SELECT m.COLB FROM Table_A m WHERE m.COLA='YYY' AND m.id=b.id
)
ELSE 'Not Open'
END YYY,
.
.
.
.
. -- ~150 case statement
from Test b,table_main c
where b.id=c.id
Here we have case statement which is referring same table (TABLE_A) but checking for different values(XXX,YYY,etc..,) in each statement. This is taking so much time. We are trying to optimize this insert query. Could someone help here?
Try a variation of a pivot query:
SELECT col1, col2 ,
coalesce ( max( CASE WHEN m.COLA='XXX' THEN m.COLB END ), 'Not open' ) As XXX,
coalesce ( max( CASE WHEN m.COLA='YYY' THEN m.COLB END ), 'Not open' ) As YYY,
.....
.....
coalesce ( max( CASE WHEN m.COLA='ZZZ' THEN m.COLB END ), 'Not open' ) As ZZZ
FROM Test b
JOIN table_main c ON b.id=c.id
LEFT JOIN Table_A m ON m.id=b.id
GROUP BY col1, col2
Rewrite using decode and LEFT JOIN as follows.
SELECT col1, col2 ,
decode ( m.COLA , 'XXX' , m.COLB , 'Not Open' ) XXX ,
decode ( m.COLA , 'YYY', m.COLB , 'Not Open' ) YYY ,
...
...
FROM Test b LEFT JOIN Table_A m ON m.id=b.id JOIN table_main c
ON b.id=c.id;
It is taking time because you are making several calls to a table to get your values. Simply reduce the number of calls being made to Table_A.
If the condition Table_A.id = m.id and m.COLA= 'Any Value' will always return one row then you can join the tables Table_A, Test and Table_main in a single join like below
Insert into my_table(col1, col2) values
select
decode(a.COLA,'XXX' , a.COLB , 'Not Open'),
decode(a.COLA,'YYY' , a.COLB , 'Not Open'),
...
...
from Table_A a, Test b, Table_main c
where a.id = b.id
and b.id = c.id
In case the condition may return multiple records then you can use With clause like below
Insert into my_table(col1, col2) values
with table_a as (select col1, col2 , a.COLA, a.COLB
from Table_A a, Test b, Table_main c
where a.id = b.id
and b.id = c.id
group by col1, col2,a.COLA, a.COLB)
select col1,col2,
decode(x.COLA,'XXX' , x.COLB , 'Not Open'),
decode(x.COLA,'YYY' , x.COLB , 'Not Open'),
....
....
from table_a x

Get unmatched records without using oracle minus except not in

Actually I have two table and each having column name, I just want the result which are not there in Table2
Table1
----
Name
---
|A|
|B|
|C|
|D|
Table2
------
|Name|
-----
|A|
|B|
Answer
|C|
|D|
I am able to do it by using minus
select name from table1
minus
select name from table2
select name from table1 where name
not in (
select name from table2)
But my Manager ask me to do it with other alternate solution without using minus,except,not in.
Is there a way to do that, It will be great if someone can help me on it.
I need to do it with oracle pl/sql
The one option left with you is using NOT EXISTS
SELECT t1.name
FROM table1 t1
WHERE NOT EXISTS (SELECT 'X'
FROM table2 t2
WHERE t2.name = t1.name);
Update: Using Join
with table_ as
(
select t1.name t1_name, t2.name t2_name
from table1 t1
left join table2 t2
on t1.name = t2.name)
select t1_name
from table_
where t2_name is null;
Or just
select t1.name
from table1 t1
left join table2 t2
on t1.name = t2.name
where t2.name is null;
Another alternative is to use an outer join and then filter rows that don't have a value in the 2nd table:
with t1 as (select 'A' name from dual union all
select 'B' name from dual union all
select 'C' name from dual union all
select 'D' name from dual),
t2 as (select 'A' name from dual union all
select 'B' name from dual)
select t1.name
from t1
left outer join t2 on (t1.name = t2.name)
where t2.name is null;
NAME
----
D
C

SQL Server 2012: Update table with inner join after sorted

I am using SQL Server 2012. I have a table called table1 like below:
Id col1 col2 col3 Name
1 a b abc null
2 b c mno null
And I have another table table2, like below:
Id col1 col2 col3 Name
1 % % abc Name1
2 a % abc Name2
3 % b abc Name3
4 a b abc Name4
I have to update Name column in Table1 From Name column in Table2 based on columns: col1, col2 and col3.
The Id = 1 in the table1 finds all 4 matches in the table because I am using like operator in col1 and col2 to compare(why I am using like is if it didn't find exact match it should accept % as a match).
Now my problem is if exact match is there for the columns col1, col2 and col3 in the table, it should consider that only not the rows with '%' value. For example, for the Id=1 in the table1, the result should be from id=4 in the table2.
I tried with following query:
UPDATE table1
SET name = t2.Name
FROM (SELECT TOP 1
t1.id, t2.name
FROM table1 t1
INNER JOIN table2 t2
ON t1.col3 = t2.col3 AND t1.col1 LIKE t2.col1
AND t1.col2 LIKE t2.col2
ORDER BY t2.col1, t2.col2) AS t3
WHERE id = t3.id;
But I am not getting result which I expected. And also, there are 8,000,000 records are there in table1 so it should not affect performance.
Please help to fix this issue.
At a first try, I suggest this:
UPDATE table1
SET name = t2.Name
FROM (SELECT TOP(1) *
FROM (SELECT
t1.id, t2.name, t2.col1, t2.col2, 2 As ord
FROM table1 t1
INNER JOIN table2 t2
ON t1.col3 = t2.col3 AND t1.col1 LIKE t2.col1
AND t1.col2 LIKE t2.col2
UNION ALL
SELECT
t1.id, t2.name, t2.col1, t2.col2, 1 As ord
FROM table1 t1
INNER JOIN table2 t2
ON t1.col3 = t2.col3 AND t1.col1 = t2.col1
AND t1.col2 = t2.col2
) DT
ORDER BY ord, col1, col2) AS t3
WHERE id = t3.id;

Resources