Conversion of Oracle join to Ansi join - sql

I need to convert the following Oracle SQL to ANSI SQL.
Select t1.c1, t2.c2, t1.c3 from t1, t2 where
T1.c1=t2.c1(+) and
T1.c2=t2.c2(+) and
T1.c3=t2.c3 and
T1.c4=t2.c4 and
T1.c1='1'

This would be outer join if all columns in t2 had the (+) modifier.
That would look like:
Select t1.c1, t2.c2, t1.c3
from t1 left join
t2
on T1.c1 = t2.c1 and T1.c2 = t2.c2 and
T1.c3 = t2.c3 and T1.c4 = t2.c4
where T1.c1 = '1';
However, your version is an inner join, because some of the columns do need to match -- so there needs to be a matching row in the second table.
So, the real equivalent is just:
Select t1.c1, t2.c2, t1.c3
from t1 join
t2
on T1.c1 = t2.c1 and T1.c2 = t2.c2 and
T1.c3 = t2.c3 and T1.c4 = t2.c4
where T1.c1 = '1';
And the (+) is not relevant.

Related

Subquery in Inner join - Multi-part identifer could not be bound

I have the following query and I am getting a multi-part identifier could not be bound exception. I realize why and my next thought was to use a CROSS APPLY, which didn't work. What I really need to do is join that subquery to make sure I get the most recent entry for a particular column.
Unfortunately, I've run out of ideas... How do I accomplish this query?
SELECT t1.*
FROM dbo.Table1 t1 (nolock)
INNER JOIN
(
SELECT TOP 1 t2_s.c1, t2_s.c2, t2_s.c4
FROM dbo.Table2 t2_s
WHERE t2_s.c1 = t1.c1
ORDER BY t2_s.dateStamped DESC
) t2
on t2.c1 = t1.c1
INNER JOIN dbo.Table3 t3
on t3.c1 = t2.c2 and t3.c2 = 1
WHERE t1.c2 = 'xxx'
Assuming you are using SQL Server, then CROSS APPLY should do what you want:
SELECT t1.*
FROM dbo.Table1 t1 (nolock) CROSS APPLY
(SELECT TOP 1 t2_s.c1, t2_s.c2, t2_s.c4
FROM dbo.Table2 t2_s
WHERE t2_s.c1 = t1.c1
ORDER BY t2_s.dateStamped DESC
) t2 INNER JOIN
dbo.Table3 t3
on t3.c1 = t2.c2 and t3.c2 = 1
WHERE t1.c2 = 'xxx';

Query optimization in SQL Server

SELECT
T2.Entity1Id, T1.Entity1Id
FROM
T1
FULL OUTER JOIN
T2 ON T1.c2 = T2.c2 AND T1.c1 = T2.c1 AND T1.c3 = 1
WHERE
((T1.c1 = 123 ) OR (T2.c1 = 123))
AND (T1.c3 = 1 OR T1.c3 IS NULL)
Above query is taking 12 seconds in SQL Server 2014, any idea to tune the query? There are indexes on C1,C2,C3 columns.
Observation: in the above query, when I remove a condition from OR (i.e.
SELECT
T2.Entity1Id, T1.Entity1Id
FROM
T1
FULL OUTER JOIN
T2 ON T1.c2 = T2.c2 AND T1.c1 = T2.c1 AND T1.c3 = 1
WHERE
(T1.c1 = 123) AND (T1.c3 = 1 OR T1.c3 IS NULL)
then it's returning results in 0 seconds.
Each table has around 500'000 records.
First, the final condition (T1.c3 = 1 OR T1.c3 IS NULL) is redundant. Given the join condition, these are the only possible values. So, the query is:
SELECT T2.Entity1Id, T1.Entity1Id
FROM T1 FULL OUTER JOIN
T2
ON T1.c2 = T2.c2 AND T1.c1 = T2.c1 AND T1.c3 = 1
WHERE (T1.c1 = 123 ) OR (T2.c1 = 123)
If this doesn't have good performance, consider breaking this into two queries:
SELECT T2.Entity1Id, T1.Entity1Id
FROM T1 LEFT JOIN
T2
ON T1.c2 = T2.c2 AND T1.c1 = T2.c1 AND T1.c3 = 1
WHERE T1.c1 = 123
UNION
SELECT T2.Entity1Id, T1.Entity1Id
FROM T2 LEFT JOIN
T1
ON T1.c2 = T2.c2 AND T1.c1 = T2.c1 AND T1.c3 = 1
WHERE T2.c1 = 123
Sometimes, the optimization of the separate subqueries is much better than the optimization for the full outer join.

UPDATE one SQL table based on equality of two columns with two columns from another table

I'm using SQL Server 2012 and I have this problem.
I want to update Table1, column 3 (with a lot of duplicate rows) with values from Table 2, column 3 (c3), where Table1.c1 = Table2.c1 and Table1.c2 = Table2.c2 (Table2 contains explanation for every row, and Table1 has a lot more rows which are also duplicates).
Here's example
I tried this query, but it doesn't work:
UPDATE T1
SET c3 = T2.c3
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.c1 = T2.c1 AND T1.c2 = T2.c2
EDIT:
Query above is OK! I had some invisible strings in my columns. Thank you Xiaoguang Qiao
I didn't see any problem with the query itself. First check data will be updated by selecting
SELECT T1.C3, T2.C3
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.c1 = T2.c1 AND T1.c2 = T2.c2
If it returns 0 rows, I think you need to check C1 and C2 one by one. Maybe there are invisible spaces in column C1 or C2. Try following query
SELECT T1.C1, T2.C1, CASE WHEN T1.C1 = T2.C1 THEN 'Same' ELSE NULL END AS "Same C1",
T1.C2, T2.C2, CASE WHEN T1.C2 = T2.C2 THEN 'Same' ELSE NULL END AS "Same C2"
FROM Table1 AS T1, Table2 T2

SQL SERVER 2005 CASE WHEN THEN END

I am running following query..
Select T1.* from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END AS COMMENTS
Its giving me Syntax error near AS. Unable to figure out the error.
You don't need the AS alias when using case in an order by
Select T1.* from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END
It's because you are trying to assign an alias to the ORDER BY clause - this is not allowed and I'm not sure what you want to achieve here?
You either need:
Select T1.* from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END
Or, if you want that CASE value to be returned in the SELECT as well, then you need:
Select T1.*, Case When T1.C1 = 'ABC' THEN 'XYZ' END AS COMMENTS
from T1
LEFT JOIN T2 ON T1.C1 = T2.C1
LEFT JOIN T3 ON T2.C3 = T3.C3
ORDER BY Case When T1.C1 = 'ABC' THEN 'XYZ' END
Also, again not sure of intention here so it depends, but you may need an ELSE on that CASE...
e.g.
ORDER BY CASE WHEN T1.C1 = 'ABC' THEN 'XYZ' ELSE T1.C1 END

Joining 3 tables to get only two rows

I have three table I need to query table 1,2 and 3 and select C1 from Table 1 and C2 from table 2 and 3 respectively so that it would give result. Is there any way of getting this?
Yes:
select t1.c1, coalesce(t2.c2, t3.c2) c2
from Table1 t1
left join Table2 t2 on t1.c1 = t2.c1
left join Table3 t3 on t1.c1 = t3.c1
Try the following:
SELECT T1.C1, T2.C2
FROM T1
INNER JOIN T1.C1 = T2.C1
UNION ALL
SELECT T1.C1, T3.C2
FROM T1
INNER JOIN T1.C1 = T3.C1