I am trying to select a record out of the table1 by joining table2 and using table2 columns in the WHERE statement. Col1 and Col2 in table1 can be stored in col1 of table2. I need to join col1 of table2 with either the value of col1 or col2 in table1
here is the sql statement I created so (pseudo):
SELECT
t1.Col1,
t1.Col2,
t1.Col3,
t1.Col4
FROM
table1 t1
JOIN table2 t2 on t2.Col1 = t1.Col1 or t2.Col1 = t1.Col2
What would be the best way to approach this?
That should be fine. Another way to write the same condition is as follows:
... JOIN table2 t2 on t2.Col1 IN (t1.Col1, t1.Col2)
It shouldn't matter which way you do it in this case. Do what you find more readable.
If I understand your questoion correctly, your SQL query is perfectly fine.
Related
I am having some trouble using a subquery for the IN clause of a query.
Hard-coding the IN .. values allows the query to execute quickly, but using a subquery slows everything down. Is there a way to speed this query up?
SELECT col1, col2, col3 FROM table1
WHERE ...
and col1 in (SELECT col1 FROM table2)
...
*The values for the IN clause will be a list of strings
SELECT col1, col2, col3 FROM table1
WHERE ...
and col1 in ('str1', 'str2', 'str3', ...)
...
The above works fine.
EDIT:
I think I was oversimplifying the problem. The query I am trying to execute looks like this:
SELECT col1, col2, col3, ...
FROM table1 t1, table2 t2
WHERE t1.col1 IN (SELECT col FROM table3)
and t1.col2 < 50
and t2.col3 = t1.col3
...
You cant write select * from . If you give select * from, it doesnot understand which column to compare with from table2. Use the column name you need.
SELECT * FROM table1
WHERE ...
and col1 in (SELECT col1 FROM table2)
...
Use JOIN instead,
and keep an index defined on table1.col1 or table2.col3 or table1.col3 or table3.col :
SELECT col1, col2, col3, ...
FROM table1 t1
INNER JOIN table2 t2 on ( t2.col3 = t1.col3 )
INNER JOIN table3 t3 on ( t1.col1 = t3.col )
WHERE t1.col2 < 50;
Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax. You should write the query as:
SELECT col1, col2, col3, ...
FROM table1 t1 JOIN
table2 t2
ON t2.col3 = t1.col3
WHERE t1.col1 IN (SELECT col FROM table3) AND
t1.col2 < 50;
I would write this using EXISTS, rather than IN:
SELECT col1, col2, col3, ...
FROM table1 t1 JOIN
table2 t2
ON t2.col3 = t1.col3
WHERE EXISTS (SELECT 1 FROM table3 t3 WHERE t1.col1 = t3.col) AND
t1.col2 < 50;
The filtering is all on table1; however, the columns are being compared with inequalities. I would try the following indexes: table2(col3), table1(col2, col1), and table3(col).
I have table1 :col1, col2, col3 and table2: col1, col2, col3
My goal is to get all records
where
t2.col1 like t1.col1 and
t2.col2 like t1.col2 and
t2.col3 like t1.col3
........................................
One variant is the inner join method
select * from t2 inner join t1 on
t2.col1 like t1.col1 and
t2.col2 like t1.col2 and
t2.col3 like t1.col3
........................................
Another variant is a stored procedure based on the 'where' clause:
select * from t2
where t2.col1 like parameter1 and
t2.col2 like parameter2 and
t2.col3 like parameter3
Then I call the procedure in VBA and I use a for next loop to go through all values/parameters from an excel table1
........................................
Execution time for the join method is slower(~20, 30%) than vba+sp method, but unfortunately, for a big set of parameters, excel freeze.
........................................
Is possible to apply loop method and go thru table1 values, as parameters for the stored procedure, inside sql server, in a sql script, no vba or c++ or perl etc. ?
I am a user with no access to db/tables design.
Thank you
First of all, your two queries in the question are not equivalent:
select * from t2 inner join t1 on
t1.col1 like t2.col1 and
t1.col2 like t2.col2 and
t1.col3 like t2.col3
Here you have t1 like t2
select * from t2
where t2.col1 like parameter1 and
t2.col2 like parameter2 and
t2.col3 like parameter3
Here it is other way around t2 like t1.
End result would be different.
Based on the sample data it looks like it should be t2 like t1.
You can try to re-write the query using CROSS APPLY instead of JOIN, but it is unlikely to make any difference in performance.
SELECT *
FROM
t1
CROSS APPLY
(
SELECT
FROM t2
WHERE
t2.col1 like t1.col1
and t2.col2 like t1.col2
and t2.col3 like t1.col3
) AS A
;
This query structure mimics your stored procedure approach where for each row from t1 you select a set of rows from t2.
I have a requirement to join two tables Conditionally.
For Ex:
T1
--Col1
--Col2
--Col3
T2
--Col1
--Col2
--Col3
Join T1 and T2 on Col1 from both tables, If Col1 is NULL then join T1 and T2 on Col2 from both tables.
How to achieve this?
you can use a query like below, which uses case condition in join crtieria
select *
from
t1 join t2
on
case
when (t1.col1 is NULL or t2.col1 is NULL)
then t1.col2
else t1.col1
end
=
case
when (t1.col1 is NULL or t2.col1 is NULL)
then t2.col2
else t2.col1
end
Your conditions are ambiguous. What if col1 is NULL in only one table?
In any case, you can specify the logic as something like:
select . . .
from t1 join
t2
on (t1.col1 = t2.col1) or
( (t1.col1 is null or t2.col1 is null) and t1.col2 = t2.col2)
The first condition will fail if either column is NULL.
SELECT
*
FROM
T1 INNER JOIN T2
ON T1.COL1=T2.COL1 OR T1.COL2=T2.COL2
I am using Inline view. Check this query.
select * from
(select t1.col1,t1.col2,t1.col3 from table1 t1)q1,
(select t2.col1,t2.col2,t2.col3 from table1 t2)q2
where t1.col1=t2.col1 or t1.col2=t2.col2;
Thanks All :)
I just tot of the below query, let me know if this works.
Select * from
(select col1, col2, col3, coalesce(col1, col2) as join_key)q1,
(select col1, col2, col3, coalesce(col1, col2) as join_key)q1,
where q1.join_key = q2.join_key
I have three tables Table1, Table2 and Table3 and the following query which deletes rows in Table1
delete from Table1
where EXISTS
(select (1) from Table2
where Table1.col1=Table2.col1
AND Table1.col2=Table2.col2
AND Table1.col3=(select **Table3.col3 from Table3** inner join Table2 on Table3.col1=Table2.col1)
Is this query correct? If not, how to use a third table inside the where condition?
Edit : Also, please explain how to rewrite the query if we want to delete the rows from table2 which itself is joined with table3?
Here's one way to do it:
delete from table1
where (col1, col2, col3) in (
select t1.col1, t1.col2, t1.col3
from table1 t1
join table2 t2 on t1.col1 = t2.col1 and t1.col2 = t2.col2
join table3 t3 on t1.col3 = t3.col3 and t2.col1 = t3.col1
);
SQL Fiddle Demo
Or using EXISTS might be faster:
delete table1
where exists (
select *
from table2
join table3 on table2.col1 = table3.col1
where table1.col3 = table3.col3 and
table1.col1 = table2.col1 and
table1.col2 = table2.col2);
I have 2 tables table A and table B. In table B we have to check if all the column entered is exactly as in table A, means if a row exists in table B then the same row will be there in table A too. also table A may have rows which are not in table B. if there is a row which is not in table A and is there in table B, an alert should be displayed showing which element is extra in table B.
Can we do this using join? if so what will be the sql code?
this is the best picture about joins i've ever seen :)
You probably want to have a look at the following article
SQL SERVER – Introduction to JOINs – Basic of JOINs
This should give you a very clear understanding of JOINs in Sql.
From there you should be able to find the solution.
As an example, you would have to look at something like
TABLE1
Col1
Col2
Col3
Col4
TABLE2
Col1
Col2
Col3
Col4
--all rows that match
SELECT *
FROM TABLE1 t1 INNER JOIN
TABLE2 t2 ON t1.Col1 = t2.Col1
AND t1.Col2 = t2.Col2
...
AND t1.Col3 = t2.Col3
--rows only in TABLE1
SELECT *
FROM TABLE1 t1 LEFT JOIN
TABLE2 t2 ON t1.Col1 = t2.Col1
AND t1.Col2 = t2.Col2
...
AND t1.Col3 = t2.Col3
WHERE t2.Col1 IS NULL
--rows only in TABLE2
SELECT *
FROM TABLE1 t2 LEFT JOIN
TABLE2 t1 ON t1.Col1 = t2.Col1
AND t1.Col2 = t2.Col2
...
AND t1.Col3 = t2.Col3
WHERE t1.Col1 IS NULL
If you want to compare based on single column, then you can do something like this:
SELECT ID FROM B LEFT JOIN A ON B.ID = A.ID WHERE A.ID IS NULL;
The above query will give you the list of records that are not present in A but in B.
Instead if you want to compare the entire row, you can use the following approach:
SELECT COUNT(*) FROM B;
SELECT COUNT(*) FROM A;
SELECT COUNT(*) FROM (
SELECT * FROM B UNION SELECT * FROM A
)
If all the queries returns the same count then you can assume that both the tables are exactly equal.