Convert NOT IN query to LEFT JOIN - sql

to adapt to Netezza DB I need to convert fallowing query(as NOT IN(SUBQUERY) is not supported by Netezza):
UPDATE table1 t1 SET t1.deal_type=t2.deal_type
FROM table2 t2
WHERE t1.id_col=t2.id_col
AND t1.price=t2.price
AND t1.id_col2=t2.id_col2
AND t2.price NOT IN (
SELECT st1.price
FROM table1 st1, table2 st2
WHERE st1.id_col=st2.id_col
AND st1.price=st2.price
AND st1.id_col2=st2.id_col2
AND st1.id_col=t1.id_col
AND t2.deal_type=st2.deal_type
GROUP BY st1.id_col, st1.price, st1.id_col2, st2.deal_type
HAVING COUNT (*)>1);
I tried with LEFT JOIN but not all records returned:
UPDATE table1 t1 SET t1.deal_type = t2.deal_type
FROM table2 t2
LEFT JOIN
(SELECT st1.price, st1.id_col, st2.deal_type
FROM table1 st1, table2 st2
WHERE st1.id_col=st2.id_col
AND st1.price=st2.price
AND st1.id_col2=st2.id_col2
GROUP BY st1.id_col, st1.price, st1.id_col2, st2.deal_type
HAVING COUNT (*)>1) subq ON (subq.id_col=t1.id_col
AND t2.deal_type=subq.deal_type)
WHERE
t1.id_col=t2.id_col
AND t1.price=t2.price
AND t1.id_col2=t2.id_col2
subq.price is null
Any suggestions where I was wrong. or any other way to work arround NOT IN witch is not supported by NETEZZA

I think you forgot to add the price to the Left Join condition.
if there are duplicates for this id&type but with different price,
the NOT-IN condition will pass, but the Left-Join (IS NULL) condition will fail
just change
ON (subq.id_col=t1.id_col
AND t2.deal_type=subq.deal_type)
to
ON (subq.id_col=t1.id_col
AND t2.deal_type=subq.deal_type)
AND subq.price=t2.price)

Can you please try this if netezza support EXISTS and your first query is logically right
UPDATE t1 SET t1.deal_type=t2.deal_type
FROM table1 t1
INNER JOIN table2 t2 ON t1.id_col=t2.id_col
AND t1.price=t2.price
AND t1.id_col2=t2.id_col2
LEFT JOIN ( SELECT st1.id_col
FROM table1 st1
INNER JOIN table2 st2 ON st1.id_col=st2.id_col
AND st1.price=st2.price
AND st1.id_col2=st2.id_col2
AND t2.deal_type=st2.deal_type
GROUP BY st1.id_col, st1.price, st1.id_col2, st2.deal_type
HAVING COUNT (*)>1) i ON i.id_col=t1.id_col
WHERE i.id_col IS NULL

Related

Using Join and Between to Link Tables and Find Values

I am trying to join these two tables and get a result, keep all results from Table 1 and find the value from Table 2 (return NULL if nothing is found in Table 2 matching criteria)
TABLE1
|ROUTE|MEASURE|
|:---:|:-----:|
|1|6|
|1|12|
|2|1|
|3|2|
|3|5|
TABLE2
|ROUTE|BEGINMEASURE|ENDMEASURE|VALUE|
|:---:|:-----:|:--:|:--:|
|1|0|5|A|
|1|5|10|B|
|2|0|5|C|
|3|0|3|D|
|3|3|10|E|
|3|10|12|F|
My code is:
select t1.route, t1.measure, t2.value
from table1 t
left join table2 t2 on t1.route=t2.route
where t1.route=t2.route and t1.measure between t2.beginmeasure and t2.endmeasure;
Add the condition to the join:
select t1.route, t1.measure, t2.value
from table1 t
left join table2 t2 on t1.route=t2.route and t1.measure between t2.beginmeasure and t2.endmeasure;

Fectch uncommon ID between two columns

I have two tables and I need to fetch if any one ID is not present in the table 2. I tried the query but its not giving the correct result. Kindly suggest.
TABLE 1
TABLE 2
Output Should be: Because Release ID and purchase ID is not present in both the columns.
QUERY Tried :
SELECT T1_ID
FROM T1 LEFT OUTER JOIN T2
ON t1.RELEASEID=t2.RELEASEID
LEFT OUTER JOIN T2 t3
ON t1.PURCHASEID=t3.PURCHASEID
WHERE IFNULL(T2.RELEASEID,'') ='' OR IFNULL(T3.PURCHASEID,'')=''
You can use NOT EXISTS as follows:
select * from t1
where not exists (select 1 from t2
where t1.releaseid =t2.releaseid or t1.purchaseid =t2.purchaseid)
You can also use LEFT JOIN as follows:
select t1.*
from t1 left join t2
on t1.releaseid =t2.releaseid or t1.purchaseid =t2.purchaseid
where t2.t2_id is null
One method is not exists:
select t1.*
from t1
where not exists (select 1
from t2
where t2.releaseid = t1.releaseid
) and
not exists (select 1
from t2
where t2.purchaseid = t1.purchaseid
);
This should work regardless of whether ? is really a string or is supposed to represent NULL.
Note: This can take advantage of indexes on t2(releaseid) and t2(purchaseid), which can be a big boost to performance on larger data.
I think you want:
select t1.*
from table1 t1
where
(t1.release_id = '?' and t2.purchase_id = '?')
or not exists (
select 1
from table2 t2
where t1.release_id in ('?', t2.release_id)
and t1.purchase_id in ('?', t2.purchase_id)
)
If the question mark is supposed to represent null values, you can just replace all instances of = '?' with is null.
Please try this and let me know if it works.
SELECT * FROM TABLE1 WHERE NOT EXISTS (SELECT '1' FROM TABLE2 WHERE TABLE1 .RELEASEID=TABLE2.RELEASEID OR TABLE1 .PURCHASEID=TABLE2.PURCHASEID);

Sum Column in Joined Table and add as column SQL

So say I have two tables in Oracle SQL (not actually data but for ease should highlight my question)
Table1 that contains only Order_id and Order_quantity and Table2 that contains only Order_id and Order_price
Then I join them as follows
Select T1.Order_id,
T1.Order_quantity,
T2.Order_price,
T1.Order_quantity*T2.Order_price As "Order_amount",
Sum(Order_amount) As "Total_Sales"
from Table1 T1
inner join Table2 T2
on T1.Order_id = T2.Order_id
So essentially I want to have two extra columns, one as the product of columns from the two tables, and another as the sum of that column in my joined table(so every entry will be the same). However as you need to
SUM(variable_name) From Table_Name
Can I assign a variable name to my new table and then refer to that. I tried the following but I'm getting a SQL command not properly ended error
Select T1.Order_id,
T1.Order_quantity,
T2.Order_price,
T1.Order_quantity*T2.Order_price As "Order_amount",
Sum(Order_amount) from New_Table As "Total_Sales"
from (Table1 T1
inner join Table2 T2
on T1.Order_id = T2.Order_id) As New_Table
Thanks for any assistance, apologies as I have a pretty naive understanding of SQL at present
I think you just want a window function:
select T1.Order_id, T1.Order_quantity, T2.Order_price,
T1.Order_quantity*T2.Order_price As order_amount,
sum(T1.Order_quantity*T2.Order_price) over () As Total_Sales
from Table1 T1 inner join
Table2 T2
on T1.Order_id = T2.Order_id
You cannot re-use the alias order_amount in the select. You need to repeat the expression -- or use a subquery or CTE to define it.
If your DBMS doesn't have a window function supports then you can use subquery instead
select order_id, Order_quantity,
(select t1.Order_quantity * t2.Order_price
from table2 t2
where t2.Order_id = t1.Order_id) as Order_amount,
(select sum(t1.Order_quantity * t2.Order_price)
from table2 t2
where t2.Order_id = t1.Order_id) as Total_Sales
from table1 t1;

Need help in postgreSQL query

I have two tables, table1 and table2. I have written the query with some condition as follows
Select t2.employee_id,
t2.adddate,
t2.previousaleave
from table2 as t2, table1 as t1
WHERE t1.enddate IS NULL
OR t1.enddate>t2.adddate
AND t2.adddate<=now()
AND t2.leavetype='annualleave'
If i run this,the conditions are not working.It is selecting all the empids of the table t2.?I checked that the problem is with the t1.enddate is NULL condition. Since the enddate column can be either,
some date
or, null
I need to get the empid if the t1.enddate IS NULL and the other conditions succeed. Here leave type is distinct with in each empid. (Each employee have only one row for the annualleave). Is there any other alternative way to do this.
You always need parentheses if using OR
For example:
Select t2.employee_id,t2.adddate,t2.previousaleave
from table2 as t2
Inner join table1 as t1 ON ............. ?????
WHERE (t1.enddate IS NULL OR t1.enddate>t2.adddate AND t2.adddate<=now())
AND t2.leavetype='annualleave'
BUT ALSO NOTE you don't appear to have joined the tables. Always use explicit ANSI join syntax to avoid creating an accidental Cartesian product of the rows from the tables.
If empid exists in both tables try
Select t2.employee_id,t2.adddate,t2.previousaleave
from table2 as t2
Inner join table1 as t1 ON t2.empid = t1.empid
WHERE (t1.enddate IS NULL OR t1.enddate>t2.adddate AND t2.adddate<=now())
AND t2.leavetype='annualleave'
SELECT t2.employee_id, t2.adddate, t2.previousaleave
FROM table2 AS t2
INNER JOIN table1 as t1
ON (
( t1.enddate IS NULL OR t1.enddate > t2.adddate )
AND t2.adddate <= now()
AND t2.leavetype = 'annualleave'
)
Is it possible for t2.adddate to be > now()? That seems awkward.

Complex SQL Join on sub query with top 1 records

I'm trying to write a query that looks something like below.
select t1.t1c1, t1.t1c2, t2.t2c3, t2.t2c4
from table1 t1
left outer join (select top 1 t2c1, t2c2, t2c3, t2c4 from table2
where t2c5 in (select t3c1 from table3 t3
where **t3c2 = t1.t1c2 and t3c3 = t1.t1c3**) t2
on t1.t1c1 = t2.t2c1 and t1.t1c2 = t2.t2c2
What SQL Server does not allow is the highlighted text above - i.e. referencing the table1's columns in the table3 sub query.
Is there a way to achieve this?
I understand that this might not be the most optimal way, is there any other way to achieve this?
You seem to exactly want outer apply. I think it would look like this:
select t1.t1c1, t1.t1c2, t2.t2c3, t2.t2c4
from table1 t1 outer apply
(select top 1 t2c1, t2c2, t2c3, t2c4
from table2
where t2c5 in (select t3c1
from table3 t3
where t3c2 = t1.t1c2 and t3c3 = t1.t1c3
) and
t1.t1c1 = t2.t2c1 and t1.t1c2 = t2.t2c2
) t2;
APPLY is a lot like using a correlated subquery, except it goes in the FROM clause and can return multiple columns and multiple rows.
Note: You should be using ORDER BY when you use TOP.