how can be write the below query efficiently
SELECT DISTINCT a.id
FROM table1 a where a.id NOT IN (SELECT DISTINCT b.id
FROM table2 b)
Post this query the result is inserted into table2 via an insert query.
The problem is that table1 has approx ~75300 records and table2 has ~74000 records.
This query is to be executed every 10 mins and it takes approx 1.5 mins to execute.
Any possibilities this query could be faster?
Try using a Join
SELECT DISTINCT a.id from table1 a
LEFT JOIN table2 b
on a.id = b.id
Where b.id is null
The Left Join clause will select all rows from a regardless of whether or not there are matching rows in b. You then can use the where clause at the end to ensure that the rows returned from a have no match in b
Related
I have a sample query
SELECT COUNT(counts)
FROM
(SELECT COUNT(*) AS counts
FROM table AS table1
LEFT JOIN table_2 as table2 ON table2.id = table1.pr_id
WHERE table1.active = 1
GROUP BY table1.column1) as t
I got the result
20563
The result was correct, but it was so slow, I had to wait up to 15 seconds for 1 query
15 seconds is too big, is there any way I can improve the speed as quickly as possible?
Thanks everyone!
Inner counting makes no sense. So
SELECT COUNT(*) FROM (
SELECT DISTINCT table1.column1
FROM table AS table1
LEFT JOIN ....
WHERE ....
) as t
The index which matches joining condition and further WHERE / DISTINCT will improve.
PS. Check does LEFT makes sense, maybe INNER JOIN is enough.
When I run the following query I get 2769 rows returned.
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t2.account_id = t1.account_id;
However, when I add the WHERE clause below, I get 692 Lines returned.
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t2.account_id = t1.account_id
WHERE t2.account_id IN (t1.account_id);
I thought that the condition established by my LEFT JOIN would the same condition established by my WHERE clause (i.e. that these two lines would effectively be redundant).
This is clearly not the case, but I cannot figure out why.
The left join returns all records of t1 and returns null for the columns of t2 for all records where the join could not be made.
But the where clause filters all data, no matter from which table. So when you filter on t2 in your where clause then all records where the join could not be made (and the t2.account_id is null) get excluded from the result since null != t1.account_id.
So basically your where clause turn your left join into an inner join.
Query 1:
SELECT sum(total_revenue_usd)
FROM table1 c
WHERE c.irt1_search_campaign_id IN (
SELECT assign_id
FROM table2 ga
LEFT JOIN table3 d
ON d.campaign_id = ga.assign_id
)
Query 2:
SELECT sum(total_revenue_usd)
FROM table1 c
LEFT JOIN table2 ga
ON c.irt1_search_campaign_id = ga.assign_id
LEFT JOIN table3 d
ON d.campaign_id = ga.assign_id
Query 1 gives me the correct result where as I need it in the second style without using 'in'. However Query 2 doesn't give the same result.
How can I change the first query without using 'in' ?
The reason being is that the small query is part of a much larger query, there are other conditions that won't work with 'in'
You could try something along the lines of
SELECT sum(total_revenue_usd)
FROM table1 c
JOIN
(
SELECT DISTINCT ga.assign_id
FROM table2 ga
JOIN table3 d
ON d.campaign_id = ga.assign_id
) x
ON c.irt1_search_campaign_id = x.assign_id
The queries do very different things:
The first query sums the total_revenue_usd from table1 where irt1_search_campaign_id exists in table2 as assign_id. (The outer join to table3 is absolutely unnecessary, by the way, because it doesn't change wether a table2.assign_id exists or not.) As you look for existence in table2, you can of course replace IN with EXISTS.
The second query gets you combinations of table1, table2 and table3. So, in case there are two records in table2 for an entry in table1 and three records in table3 for each of the two table2 records, you will get six records for the one table1 record. Thus you sum its total_revenue_usd sixfold. This is not what you want. Don't join table1 with the other tables.
EDIT: Here is the query using an exists clause. As mentioned, outer joining table3 doesn't alter the results.
Select sum(total_revenue_usd)
from table1 c
where exists
(
select *
from table2 ga
-- left join table3 d on d.campaign_id = ga.assign_id
where ga.assign_id = c.irt1_search_campaign_id
);
I have a query like this:
SELECT q,COUNT(x),y,
(SELECT i FROM (SELECT q,w FROM tableA WHERE conds)
JOIN tableC ON (cond)
WHERE id = t.q)
FROM (SELECT q,w FROM tableA WHERE conds) t
JOIN tableB
GROUP BY q
The subquery (SELECT q,w FROM tableA WHERE conds) returns several hundred rows. After the GROUP BY q there is around 20 rows left.
The subquery (SELECT i FROM (SELECT q,w FROM tableA WHERE conds) join tableC WHERE id = t.q) uses inside of it the exactly same subquery as the one above, but then also selects a fraction of the results based on which q value is currently being grouped.
My problem seems to be this. The performance is too slow because I can't seem to put the WHERE id = t.q inside the (SELECT q,w, FROM Table A WHERE conds) subquery. I can only guess that for every unique value of q, the query is being run, it produces hundreds of rows and then has to perform the WHERE clause on an un-indexed temporary table. I think I need to perform the WHERE before the full join
Any ideas please?
This query could produce the same results, but so much information is missing from the question, who can be sure?
Select
q,
count(x),
y,
i
From
tableA a
inner join
tableC c
on cond and c.id = a.q
cross join -- is this an inner join?
tableB b
Where
conds
Group By
q,
y,
i
I am using MySQL 5.5 and have two tables T1(ID, NAME) and T2(ID, MARKS), following is the data in the table.
T1's data
ID NAME
1 A
2 B
3 C
T2's data
ID MARKS
1 40
5 60
AND I want following resultset
ID NAME MARKS
1 A 40
2 B 0
3 C 0
What query we can write to accomplish above resultset?
LEFT JOIN the two tables:
SELECT
t1.id,
t1.name,
IFNULL(t2.Marks, 0) AS Marks
FROM T1
LEFT JOIN T2 ON t1.ID = t2.ID;
SQL Fiddle Demo
You should be using a LEFT JOIN clause for this kind of result :-)
Your query will look like this :
SELECT
ID,
NAME,
COALESCE(MARKS, 0) AS MARKS
FROM T1
LEFT JOIN T2 USING(ID)
Note that I'm using the USING clause for a more semantic and compact syntax than the ON clause.
In this case, you need to use LEFT JOIN to join both tables since it is not guaranteed that ID on table T1 will exist on table T2. LEFT JOIN retrieves all rows that are found on the lefthand side table whether it has a matching record or not on the righthand side table.
The use of COALESCE in the statement is to convert NULL values into 0. The reason why NULL exist on the values of the column is because some records on table T1 doesn't have a matching record on table T2 causing the column T2.Marks to be null.
SELECT a.ID, a.Name, COALESCE(b.Marks, 0) Marks
FROM T1 a
LEFT JOIN T2 b
ON a.ID = b.ID
SQLFiddle Demo
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins