How to convert this correlated sub query to Vertica friendly non correlated query - vertica

I have below SQL Server query and need to convert it to Vertica query.
The problem right now is vertica doesnt support multi-level correlated subqueries so in my example and t3.a = t1.a doesnt work
select * from t1
where not exists (
select * from t2
where t2.y = t1.y
and t2.x in (
select top 1 x from t3
where t3.z = t2.z
and t3.a = t1.a
order by t3.b
)
)
Can anyone please help me do this?

Vertica doesn't support more than 1 level of correlated sub-queries, you should convert them into JOINs.
It also doesn't support the TOP x clause, use LIMIT x instead.
Something like this:
SELECT t1.*
FROM t1
LEFT JOIN t2 ON t1.y = t2.y
WHERE t2.y IS NULL
AND t2.x IN
(SELECT t3.x
FROM t3
JOIN t2 ON t3.z = t2.z
JOIN t1 ON t3.a=t1.a
ORDER BY t3.b LIMIT 1);

Related

Oracle SQL query Alternative to using Condition 'value1 is NULL OR Value1 =Value2'

I am querying from 2 tables, template_table(Columns: ID, Market, Currency) & Value_table(Columns:ID, Market, Currency, x, y, z)
I only want to use the the rows from Value_table if they match to the template_table using ID field and only use the Market & Currency to match if they are not null in the template_table:
example data in template table could look like:
ID
MARKET
CURRENCY
7
IRE
EUR
7
(null)
USD
7
FRA
(null)
Template table can have many rows per template.ID.
The table is relatively small in volume, but for some reason Oracle performs slow for me. I have added INDEX on the ID Column in the TEMPLATE_TABLE but there wasn't much improvement
SELECT * FROM
VALUE_TABLE T1
JOIN TEMPLATE_TABLE T2 ON T1.ID = T2.ID
AND (T1.MARKET is Null or T1.MARKET= T2.MARKET)
AND (T1.CURRENCY is Null or T1.CURRENCY = T2.CURRENCY)
WHERE T1.ID = 7
Could there be a better way to write this query?
Thanks
You could use:
SELECT *
FROM VALUE_TABLE T1
JOIN TEMPLATE_TABLE T2
ON ( T1.ID = T2.ID
AND T2.market = COALESCE( T1.market, T2.market )
AND T2.currency = COALESCE( T1.currency, T2.currency )
)
WHERE T1.ID = 7
But I think that is more difficult to read (and you would need to check whether Oracle makes use of indexes using that method) and I think would be easier to use your original method:
SELECT *
FROM VALUE_TABLE T1
JOIN TEMPLATE_TABLE T2
ON ( T1.ID = T2.ID
AND (T1.MARKET is Null or T1.MARKET= T2.MARKET)
AND (T1.CURRENCY is Null or T1.CURRENCY = T2.CURRENCY)
)
WHERE T1.ID = 7

Workaround for delete in hive with join conditions

So i'm trying to convert a SQL delete query to Hive one. Im using hive .12 version's which doesn't supports delete.
Below is the SQL query:
Delete from t1 c where exists(select 1 from t2 a where
a.emplid=c.employee_id and a.project_status='test')
Now i tried tried using NOT IN for the above query but due to some reasons we cannot use NOT IN in our queries.
below is Hive query i have written but i'm not sure as its not giving correct results. i'm pretty new to hive. can anyone help on this.
INSERT Overwrite table t1
select * from t1 c left outer join t2 a on (c.employee_id=a.employee_id)
where a.project_status= 'test'
and a.employee_id is null
Move project_status='test' condition to the subquery or into the on clause. Also you should select columns only from table c.
Example with filter in the subquery:
insert overwrite table t1
select c.*
from t1 c
left join (select employee_id
from t2
where project_status='test'
) a on (c.employee_id=a.employee_id)
where a.employee_id is null;
Example with additional condition in the ON:
insert overwrite table t1
select c.*
from t1 c
left join t2 a on (c.employee_id=a.employee_id and a.project_status='test')
where a.employee_id is null;

replace a union query involving a left join

I have a left join and a Union .
I was thinking if it is possible to replace the union with a join
select t1.col1,t1.col2,t2.col1,
from t1
left join t2 on (t1.col1 = t2.col1)
union
select t3.col1,t3.col2,t2.col1
t2.col1,
from t3
left join t2 on (t3.col1 = t2.col1)
I am on Oracle 12c can this query be re-written without the union ?
I tried this but the results don't match the union query's results
select t1.col1,t3.col2,t2.col1,
from t1
left join t2 on (t1.col1 = t2.col1)
left join t3 on (t3.col1 = t2.col1 and t1.col1 = t2.col1)
Any ideas is this even possible ?
Here are a couple of alternatives for you:
Do the union of t1 and t3 first, before joining to t2:
select t.col1, t.col2, t2.col1
from (select col1, col2
from t1
union
select col1, col2
from t3) t
left outer join t2 on (t.col1 = t2.col1);
Use a full outer join of t1 and t3 first, before joining to t2:
select t.col1, t.col2, t2.col1
from (select coalesce(t1.col1, t3.col1) col1,
coalesce(t1.col2, t3.col2) col2
from t1
full outer join t3 on t1.col1 = t3.col1
and t1.col2 = t3.col2) t
left outer join t2 on (t.col1 = t2.col1);
N.B. Both are untested, since you neglected to provide any sample data in any of the three tables. You'll have to test these approaches yourself.
ETA: Also, I believe both these approaches should work for the example as given. If your real world scenario differs from that in your question, it's possible neither approach will be of use.
ETA2: Given you're wishing to tweak your query for readability, I'd go with my first proposed solution (assuming it works for you, of course!), since the union deduplicates the rows from tables t1 and t3 before joining to t2 - that way, you're reducing the work needed to do the join. Also, the union has less to check too (2 cols instead of 3).
It may have a union in it, but it's sure as heck nicer to read than my second suggestion! At least, in my opinion *{;-)

Return non-null value from two tables in Oracle

I have two tables, T1 and T2 with same set of columns. I need to issue a query which will return me value of columns from either table whichever is not null. If both columns are null return null as the value of that column.
The columns are c1,c2,c3,cond1.
I issued the following query. The problem is that if one subquery fails the whole query fails. Somebody please help me. Probably there is another simple way.
SELECT NVL(T1.c1, T2.c1) c1,NVL(T1.c2, T2.c2) c2,NVL(T1.c3, T2.c3) c3
FROM (SELECT c1,c2,c3
FROM T1
WHERE cond1 = 'T10') T1
,(SELECT c1,c2,c3
FROM T2
WHERE cond1 = 'T200') T2 ;
You need something like this:
SELECT NVL((SELECT T1.c1
FROM T1
WHERE T1.c2 = 'T10'),
(SELECT T2.c1
FROM T2
WHERE T2.c2 = 'T200')) AS c1
FROM dual
Or you may prefer a full outer join:
SELECT NVL(T1.c1, T2.c1) AS c1
FROM T1 FULL OUTER JOIN T2 ON 1=1
WHERE T1.c2 = 'T10'
AND T2.c2 = 'T200'
Your result is logical. If the first table is null no combination of values will exist in the natural join.
EDIT. After some new requirements we can use a hack to get the row. Lets get all three possibilities, T1, T2 or all nulls and select the first one:
SELECT *
FROM ( (SELECT T1.*
FROM T1
WHERE T1.c2 = 'T10')
UNION ALL
(SELECT T2.*
FROM T2
WHERE T2.c2 = 'T200')
UNION ALL
(SELECT T2.*
FROM dual
LEFT JOIN T1 ON 1 = 0 ) )
WHERE ROWNUM = 1

left outer join on nullable field with between in join condition (Oracle)

I have two tables as: table1 with fields c1 and dt(nullable); table2 with fields start_dt, end_dt and wk_id. Now I need to perform left outer join between the table1 and table2 to take wk_id such that dt falls between start_dt and end_dt. I applied following condition but some wk_id which shouldn't be NULL are pulled NULL and some rows get repeated.
where nvl(t1.dt,'x') between nvl(t2.start_dt(+), 'x') and nvl(t2.end_dt(+), 'x');
What is wrong with the condition?
select *
from table1 t1
left join table2 t2
on t1.dt between t2.start_dt and t2.end_dt
I recommend you try the new ANSI join syntax.
Also, are you just using 'x' as an example? Or are the dt columns really stored as strings?
It seems you are missing the part "table1 left outer join table2 on table1.some_field = table2.some_field"
Something like this:
select t1.c1, t1.dt, t2.start_dt, t2.end_dt, t2.wk_id
from table1 t1 left outer join table2 t2
on t1.some_field1 = t2.some_field1
where nvl(t1.dt,'x')
between nvl(t2.start_dt, 'x') and
nvl(t2.end_dt, 'x')

Resources