I have a query say,
select col1,col2 from table1;
which return 2 columns of multiple rows. I want to use these two values in where condition of another query. Something like
select col3,col4 from table2 where col5=col1 and col6=col2;
where col1 and col2 are the resultant values of the first query.
Currently I have used inner query something like
select col3,col4 from table2
where col5 in (select col1 from table1)
and col6 in (select col2 from table1);
But I dont want to use inner query like the one shown above as it slows down bring results.
Please suggest.
JOIN them instead of using IN's like so:
SELECT t2.col3, t2.col4
FROM table2 t2
INNER JOIN
(
SELECT col1, col2
FROM table1
) t1 ON t2.col5 = t1.col1 AND t2.col6 = t1.col2
Note that, you didn't need to select specific columns in the second table. You can JOIN the second table table1 directly like so:
SELECT t2.col3, t2.col4
FROM table2 t2
INNER JOIN table1 t1 ON t2.col5 = t1.col1
AND t2.col6 = t1.col2
Related
Why would I use a LEFT JOIN in SQL in a FROM clause and attach a WHERE clause where the entity "is null"? I was told this is a very efficient script and I should learn the methodology behind it.
For example:
FROM
something
LEFT JOIN aRow a AND bRow b AND cRow c AND dRow d
WHERE
bRow.b IS NULL;
This kind of construct is used when you specifically want to know something like "a list of all customers who have never ordered anything" :
SELECT
customer.*
FROM
customers
LEFT JOIN
orders
ON
orders.customerid = customers.id
WHERE
orders.id IS NULL
Or to quote an old manager of mine: "Can you get the database to give me a list of everything that isn't in the database?"
Me> "Sure, can you give me a list of what things the database should tell you it doesn't have?"
Him> "How am I supposed to know that?"
This really is a fairly generic, non-RDBMS-specific question. The logic will apply to pretty much any flavor of SQL. And this is a technique that anyone who works with data queries should be familiar with.
For all intents and purposes (and moving past the flawed syntax in the OP), this is the same query as:
SELECT *
FROM table1
WHERE table1.col1 NOT IN (
SELECT table2.col1 FROM table2 WHERE table2.col2 = <filterHere>
)
When you are dealing with a couple of hundred rows, you may not see a significant difference in performance. But when you're working with just a few million rows in both tables, you will most definitely see a significant performance increase in
SELECT table1.*
FROM table1
LEFT OUTER JOIN table2 ON table1.col1 = table2.col1
AND table2.col2 = 42
WHERE table2.id IS NULL
Let's illustrate what is happening with these queries.
Create test tables.
CREATE TABLE table1 (col1 int, col2 varchar(10)) ;
INSERT INTO table1 ( col1, col2 )
VALUES (1,'a')
, (2,'b')
, (3,'c')
, (4,'d')
CREATE TABLE table2 (col1 int, col2 varchar(10)) ;
INSERT INTO table2 ( col1, col2 )
VALUES (1,'a')
, (3,'c')
This gives us
table1
col1 col2
1 a
2 b
3 c
4 d
table2
col1 col2
1 a
3 c
Now we want the columns that are in table1 but not in table2.
SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 NOT IN (
SELECT t2.col1 FROM table2 t2
)
We can't SELECT anything from table2, because that table is just a sub-query and not part of the whole query. It's not available to us.
This breaks down to
SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 NOT IN ( 1,3 )
Which further breaks down to
SELECT t1.col1, t1.col2
FROM table1 t1
WHERE t1.col1 <> 1
OR t1.col1 <> 3
These queries give us
col1 col2
2 b
4 d
That's a subquery broken down into 2 different OR statements to filter our results.
So lets look at a JOIN. We want all of the records on the left side, and only include those on the right side that match. So
SELECT t1.col1 AS t1_col1, t1.col2 AS t1_col2, t2.col1 AS t2_col1, t2.col2 AS t2_col2
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.col1 = t2.col1
With a JOIN, both tables are available to our SELECT, so we can see which records in tablel2 match up to those in table1. The above gives us
t1_col1 t1_col2 t2_col1 t2_col2
1 a 1 a
2 b NULL NULL
3 c 3 c
4 d NULL NULL
With the extra data, we can see that col1 for 2 and 4 don't match in the two tables. We can now filter those out with a simple WHERE statement.
SELECT t1.col1, t1.col2
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.col1 = t2.col1
WHERE t2.col1 IS NULL
Giving us
col1 col2
2 b
4 d
There's no subquery and just one statement in the filter. Plus, this allows the engine's optimizer to make a more efficient query plan.
It's impossible to see a difference in performance when we're only dealing with a couple of rows, but multiply these tables by a few million rows, and you will definitely see how much faster a JOIN can be.
I have a query like this:
UPDATE t1
SET t1.col1 = ( SELECT col1 FROM t2 WHERE <some_complex_conditions> ),
t1.col2 = ( SELECT col2 FROM t2 WHERE <some_complex_conditions> )
WHERE id = :id;
As you see, I have to execute the same query twice, every time for one column. Also as I've mentioned, that SELECT query has some complex conditions which need lots of processing. Now I want to know, how can I handle the UPDATE statement to get the update those two columns by single SELECT statement?
Something like this:
SELECT col1, col2 FROM t2 WHERE <some_complex_conditions>
In other word, how can I use this ^ into the UPDATE statement?
see multi table syntax in manual and stackoverflow
It's possible to update joined table. I think that it should be possible to join select statement, but I'm not sure, but I think example below shows equivalent query:
UPDATE t1
LEFT JOIN t2
-- joining condition, there can be the part <some complex condition>
ON t1.id = t2.ref_id AND t2.col3 = 'whatever you want'
SET t1.col1 = t2.col1, t1.col2 = t2.col2
--additional condition like WHERE t2.col1 IS NOT NULL
i am performing a sub query in mysql which is like
select col1, col2 , (select col3 from table2) as 'data'
from table1
where not data is null
how should i get data in where clause. IS it POSSIBLE
One way to do this is :
SELECT *
FROM (
select col1, col2 , (select col3 from table2) as 'data'
from table1
)t
WHERE data IS NOT NULL
As you see there I have created on derived table t for your query, now result of your query is treated as Table(temp table) and having columns as col1,col2 and col3, Using this result set we can able to access col3 in where clause .
Note - assuming that select col3 from table2 returns single value as per OP's comments
Use cross join:
select t1.col1, t1.col2, t2.col3 as data
from table1 t1 cross join
(select col3 from table2) t2
where t2.col3 is not null;
I am using mysql and I'm interested in rows where reciprocals appear in a different row in the table.
Imagine 2 columns, each with letters a through z.
Lets say row1 has a,b, row2 has a,c, and row 3 has c,a. I am interested in the pair a,c because it appears both as c,a and a,c in different rows in the table.
Do I have to use a nested select? Or perhaps an exists clause?
I believe this is what you're after, a self-join:
SELECT t1.*
FROM table1 t1
JOIN table1 t2
ON t1.col1 = t2.col2
AND t1.col2 = t2.col1
Here is a SQL fiddle demo: SQL Fiddle
also use SELECT REVERSE('abc') see http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_reverse with above #spencer7593 said
`SELECT t1.*
FROM table1 t1
JOIN table1 t2
ON t1.col1 = t2.col2
AND t1.col2 = t2.col1`
1.select col1,col2 from table1 where condition1=<<value1>>
UNION ALL
select col1,col2 from table2 condition1=<<value2>>;
2. `select col1 from table3;`
3. I need to write the 3rd query where i need the output of col1,col2 from table1 based on the col1 (sort based on col1 from table3).
I can do this way
create table as temp_table as
select col1,col2 from table1 where condition1=<<value1>>
UNION ALL
select col1,col2 from table2 condition1=<<value2>>;
SELECT t1.col1,t1.col2
FROM temp_table t1
LEFT OUTER JOIN table3 t2 ON t1.col2=t2.col2
order by t2.col1;
I want in a single query(in mysql ) & not using temp table.
Any thoughts? Thanks.
You can use the unioned result as subselect.
Look into subqueries. They're kind of like a temporary table that only exists while the query is running.
Select T.A, T.B from
(select col1 as A,col2 as B from table1 where condition1=<<value1>>
UNION ALL
select col1,col2 from table2 condition1=<<value2>>) as T,
table3 as T2
where T.A = T2.col1
order by t2.col1