Speed up a join with 2 keys - sql

Can I speed this somehow up?
CREATE TABLE TEST AS
SELECT t1.Tech, t2.Coloar,t2.Car from Table1 t1
INNER JOIN Table2 t2 on (t1.ID = t2.ID AND t1.IT = t2.IT AND t1.LIFI = t2.LIFI) OR (t1.RA = t2.RA)
where...
If I create the table just with
(t1.ID = t2.ID AND t1.IT = t2.IT AND t1.LIFI = t2.LIFI)
or with this key
(t1.RA = t2.RA)
it takes seconds, but both together a couple of minutes and I have more and bigger tables to create and sometimes I need to LEFT JOIN this key pair, like
CREATE TABLE...
INNER JOIN...
LEFT JOIN on (t1.ID = t2.ID AND t1.IT = t2.IT AND t1.LIFI = t2.LIFI) OR (t1.RA = t2.RA)

Remove the OR from the ON clause:
CREATE TABLE TEST AS
SELECT t1.Tech,
COALESCE(t2.Color, tt2.Color),
COLAESCE(t2.Car, tt2.Car)
FROM Table1 t1 LEFT JOIN
Table2 t2
ON t1.ID = t2.ID AND t1.IT = t2.IT AND t1.LIFI = t2.LIFI LEFT JOIN
Table2 tt2
ON t1.RA = tt2.RA AND t2.ID IS NULL
WHERE (t2.ID IS NOT NULL OR tt2.ID IS NOT NULL) AND
...
This should be able to take advantage of appropriate indexes for both the joins.

Try this
CREATE TABLE TEST AS
select t1.Tech, t2.Coloar,t2.Car
From Table1 t1
left join Table2 t2 on (case when t1.RA = t2.RA then 1 when t1.ID = t2.ID AND t1.IT = t2.IT AND t1.LIFI = t2.LIFI then 1 else 0 end = 1)

Related

SQL three table joins using two ids and another column

I have three tables
t1 t2 t3
I want to select data from only two of the tables but need the ids and columns from other tables for reference.
How to select data from t3 and t2
WHERE t1.id = t2.id = t3.id
AND t1.fid = t2.fid = t3.fid
AND t1.type = 'abc'
id column will be the same value for all tables. fid column will have incremental fid's but need the ones where t1.type = 'abc' also
Would this work?
select data
from t3
select data
from t2
join on t1.id = t2.id and t2.id = t3.id
join on t1.fid = t2.fid and t2.fid = t3.fid and t1.type = 'abc'
where id = 1
Generally, this kind of problem can be solved using EXISTS as follows:
select data
from t2
join t1 on t1.id = t2.id and t1.fid = t2.fid
where exists (select 1 from t3 where t2.id = t3.id and t2.fid = t3.fid)
and t1.type = 'abc'
and t1.id = 1
You could try something like this:
select columns_that_you_want
from t1 x
inner join t2 y on x.id = y.id
inner join t3 z on y.id = z.id
where x.type = 'abc'
;
This will join the three tables, and filter just the type 'abc' that you want from table t1. Also you can add more filter on the where clause in case you need to filter more the result.

Merging different conditional select queries into one - with structure

I have a query in SQL Server 2008 as below:
;with PassiveCases
AS
(
Select t1.id, COUNT(*) as PassiveCounts
from #Table1 t1
inner join Table2 t2 on t2.Id = t1.SurgicalRequest_Id
inner join Table3 t3 on t3.Id = t2.ReportingIndicator_Id
inner join Table3 t4 on t4.Id = t3.Id
where t4.Passive = 1
),
ActiveCases
AS
(
Select t1.id, COUNT(*) as ActiveCounts
from #Table1 t1
inner join Table2 t2 on t2.Id = t1.SurgicalRequest_Id
inner join Table3 t3 on t3.Id = t2.ReportingIndicator_Id
inner join Table3 t4 on t4.Id = t3.Id
where t4.Passive = 0
)
What I want it to combine these structures into one to increase the efficiency and provide more readability. I am looking for something like below (it doesn't work)
:With Cases
AS
(
Select t1.id, case when t4.Passive = 1 then COUNT(*) as PassiveCounts else COUNT(*) as ActiveCounts
from #Table1 t1
inner join Table2 t2 on t2.Id = t1.SurgicalRequest_Id
inner join Table3 t3 on t3.Id = t2.ReportingIndicator_Id
inner join Table3 t4 on t4.Id = t3.Id
)
Any help would be appreciated.
Use conditional aggregation.
Select t1.id
,sum(case when t4.Passive = 1 then 1 else 0 end) as PassiveCounts
,sum(case when t4.Passive <> 1 then 1 else 0 end) as ActiveCounts
from #Table1 t1
inner join Table2 t2 on t2.Id = t1.SurgicalRequest_Id
inner join Table3 t3 on t3.Id = t2.ReportingIndicator_Id
inner join Table3 t4 on t4.Id = t3.Id
group by t1.id
You just want conditional aggregation. In your case, though, you can do this with arithmetic:
With Cases AS (
Select t1.id, sum(t4.Passive) as PassiveCount, sum(1 - t4.Passive) as ActiveCount
from #Table1 t1 inner join
Table2 t2
on t2.Id = t1.SurgicalRequest_Id inner join
Table3 t3
on t3.Id = t2.ReportingIndicator_Id inner join
Table3 t4
on t4.Id = t3.Id
group by t1.id
)
According to your question, t4.Passive only takes on two values, so the arithmetic should do what you want.

Oracle SQL: JOIN by dblink

I use next SQL-query in Oracle DB:
SELECT T1.*,
T3.*
FROM MyTable1 T1
INNER JOIN MyTable2 T2 ON T2.Id1 = T1.Id
LEFT JOIN MyTable3#dblink1 T3 ON T3.Id2 = T2.Id
This query is very simple and fast (about 1 min, T1 contain about 1 million rows, T3 more then 10 million rows). Now I want to use MyTable4 from dblink1 for filtering selected rows data. For it, I use subquery:
SELECT T1.*,
T3.*
FROM MyTable1 T1
INNER JOIN MyTable2 T2 ON T2.Id1 = T1.Id
LEFT JOIN (SELECT Sub_T1.*
FROM MyTable3#dblink1 Sub_T1
INNER JOIN MyTable4#dblink1 Sub_T2 ON Sub_T2.Id3 = Sub_T1.Id
WHERE
Sub_T2.MyColumn1 = 'required value') T3 ON T3.Id2 = T2.Id
But this query is too slow (more then 20min). If I rewrite this query to:
SELECT T1.*,
T3.*
FROM MyTable1 T1
INNER JOIN MyTable2 T2 ON T2.Id1 = T1.Id
LEFT JOIN MyTable3#dblink1 T3 ON T3.Id2 = T2.Id
LEFT JOIN MyTable4#dblink1 T4 ON T4.Id3 = T3.Id
WHERE
T4.MyColumn1 = 'required value'
Then my query work fast again, but I donn't like result (I want to see columns of T3 as null, if WHERE return false).
How to improve my second query, for speed up it?
Does phrasing the query with parentheses solve the problem?
SELECT T1.*,
T3.*
FROM MyTable1 T1 INNER JOIN
MyTable2 T2
ON T2.Id1 = T1.Id LEFT JOIN
(MyTable3#dblink1 T3 JOIN
MyTable4#dblink1 T4
ON T4.Id3 = T3.Id AND
T4.MyColumn1 = 'required value'
)
ON T3.Id2 = T2.Id;
Or, also:
SELECT T1.*,
T3.*
FROM MyTable1 T1 INNER JOIN
MyTable2 T2
ON T2.Id1 = T1.Id LEFT JOIN
MyTable3#dblink1 T3
ON T3.Id2 = T2.Id
EXISTS (SELECT 1 FROM MyTable4#dblink1 T4 WHERE T4.Id3 = T3.Id AND T4.MyColumn1 = 'required value'
)

How to Update Column from a Column in another table

There are probably better ways, but this worked for me:
Update t1
set t1.ListKey = t2.ListKey
From Jet.LookupListItemEntity_Default t1
join (Select ListKey, Id from Jet.LookupListEntity_default) as t2
on t1.ListId = t2.id
Greg
Update t1
set t1.ListKey = t2.ListKey
From Jet.LookupListItemEntity_Default t1
join Jet.LookupListEntity_default t2 on t1.ListId = t2.id

How do I force join inside a left join branch?

I need to LEFT join to entire t2+t3 branch, but if I can find a matching join between t1 and t2, I want to enforce the t2 and t3 join.
SELECT T1.name,T2.bob,T3.a
FROM T1
LEFT JOIN T2 ON t1.id = t2.t1_id
JOIN T3 ON t2.id = T3.t2_id
What is the syntax?
Sample data:
T1 [id,name]
1 aaa
2 bbb
3 ccc
T2 [id,t1_id,bob]
1,1,777
2,1,888
2,2,999
T3[id,t2_id,a]
1,2,'yeh'
EXPECTED RESULT:
[name] , [a] , [bob]
aaa , 'yeh' , 888
bbb , NULL , NULL
ccc , NULL , NULL
EDIT: This query returns you the result as expected from your sample data -
(Also note, this query is taken with help from Treefrog's answer below) -
SELECT t1.[name], t3.a, t2.bob
FROM T2 as t2
JOIN T3 as t3 ON t3.t2_id = t2.id
RIGHT JOIN T1 as t1 ON t1.id = t2.t1_id
My Older answer -
SELECT a
FROM T1 as t1
INNER JOIN T2 as t2 ON t1.id = t2.t1_id
LEFT JOIN T3 as t3 ON t2.id = t3.t2_id
SELECT T1.a
FROM T2
JOIN T3 ON T3.t2_id = T2.id
RIGHT JOIN T1 ON T1.id = T2.t1_id
Both of these will give you your result. Not sure which would perform better.
NESTED STATEMENT:
SELECT [name], NULL AS [a], NULL AS [bob]
FROM t1
LEFT OUTER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
WHERE t3.t2_id IS NULL
AND (SELECT COUNT(*) FROM t1 AS t1b LEFT OUTER JOIN t2 AS t2b ON t1b.id = t2b.t1_id LEFT OUTER JOIN t3 AS t3b ON t2b.id = t3b.t2_id WHERE t1.id = t1b.id AND t3b.a IS NOT NULL) = 0
UNION
SELECT [name], [a], [bob]
FROM t1
LEFT OUTER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
WHERE t3.t2_id IS NOT NULL
ORDER BY t1.name
TEMPORARY TABLE:
CREATE TABLE #tmp_Rslt([name] varchar(50), [a] varchar(50), [bob] varchar(50))
--select matches
INSERT INTO #tmp_Rslt
SELECT [name], [a], [bob]
FROM t1
LEFT OUTER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
WHERE t3.t2_id IS NOT NULL
ORDER BY t1.name
--select t1's that didn't have matches
INSERT INTO #tmp_Rslt
SELECT [name], NULL AS [a], NULL AS [bob]
FROM t1
LEFT OUTER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
WHERE t3.t2_id IS NULL
AND t1.[name] NOT IN (SELECT DISTINCT [name] FROM #tmp_Rslt)
SELECT *
FROM #tmp_Rslt
--cleanup.
DROP TABLE #tmp_Rslt
This should work in MySQL
SELECT * FROM T1
LEFT JOIN (T2
INNER JOIN T3 ON T2.id=T3.t2_id
) ON T1.id= T2.t1_id