How to Avoid SubQuery with same output in MySql - php

Good Day!
I already saw other post about avoiding subquery / using JOIN statement, but still I can't figure it out why my query is so very slow to execute the 9 result data. but when the result data is more than thousands the query execute 0.7k ms only.
My question is , how can I speed up this query execution, what will I remove/add, Or do I need to re-construct the query? how?
here's my query
SELECT a.ts, b.bc, b.rem, c.dept FROM table1 a
INNER JOIN (select doc, max(ID) from table1 Group By doc) d ON d.doc=a.doc AND d.ID=a.ID
INNER JOIN table2 c ON c.u_id=a.u_id
INNER JOIN table3 b ON b.id=a.doc
WHERE c.depart = 'deparment' AND b.end = 0
here is the Screen Shot of
EXPLAIN result
Updated SS for EXPLAIN result
I already set INDEX :
ALTER TABLE table3 ADD INDEX max_id (end,id,bc);
ALTER TABLE table1 ADD INDEX max_id (ID,doc,u_id,ts,rem);
ALTER TABLE table1 ADD INDEX m_id (doc,ID);
ALTER TABLE table2 ADD INDEX user_max (dept,u_id);

Try a correlated subquery:
SELECT a.ts, b.bc, b.rem, c.dept
FROM table1 a INNER JOIN
table2 c
ON c.u_id = a.u_id INNER JOIN
table3 b
ON b.id =a.doc
WHERE c.depart = 'deparment' AND b.end = 0 AND
d.id = (SELECT MAX(t1.id) FROM table1 t1 WHERE t1.doc = a.doc);
For the correlated subquery you want an index on table1(doc, id).

Related

compare two tables with same column for similar values

I have two tables tableA and tableB. Both have two similar columns ID and B_ID.
I want to check whether both table have similar values. My code is:
$ac = $mysql->query("(SELECT ID,B_ID FROM tableA) INTERSECT (SELECT ID,B_ID FROM tableB)");
if($ac){
while($row = $ac->fetch_assoc()){
echo "ID ".$row["ID"]." B_ID".$row["B_ID"]."<br>";
}
}
But this doesn't give any result.
ps: tableA(ID,B_ID)
1->23
2->23
3->23
4->56
5->67
tableB(ID,B_ID)
3->23
8->26
11->27
12->66
here both table has 3->23 but 1->23 2->23 is not in tableB how can i figure that sort of records. same B_ID but different ID
If you have B.ID column is present in both table then use following JOIN query
SELECT a.ID, a.B_ID
FROM tableA AS a
JOIN tableB AS b ON (a.B_ID = b.B_ID AND a.ID = b.ID)
Use a join to get the data and just iterate over your results. Run the query and if there is any record that satisfies the query or not.
select t1.ID, t1.B_ID from tableA t1, tableB t2
where t1.ID = t2.ID
and t1.B_ID =t2.B_ID
Use an INNER JOIN and COUNT
SELECT COUNT(*) as cnt
FROM tableA INNER JOIN tableB
ON tableA.B_ID = tableB.B_ID AND tableA.ID = tableB.ID
now if cnt is greater than zero than common values exist, otherwise no
Please try with this query may be help full.
SELECT
tbla.ID,
tbla.B_ID
FROM
tablea AS tbla,
tableb AS tblb
WHERE
tbla.B_ID = tblb.B_ID

Join but return ALL records from Table

I have the following SQL query:
SELECT * FROM `table1` INNER JOIN `table2` ON table1.messageid=table2.messageid WHERE `venue_active` = 1
The above works fine but it only returns fields where both tables have a messageid field.
My problem is that I need it to return ALL fields from Table1 reguardless if it has a messageid match in table2 or not.
So, in other words I need ALL records to be returned from Table1 and all records from Table2 where there's a messageid that matches both.
How can I do this?
Use a LEFT JOIN rather
SELECT *
FROM `table1` LEFT JOIN
`table2` ON table1.messageid=table2.messageid
WHERE `venue_active` = 1
That said, it will only work if venue_active is also part of table1, and not table2.
Have a look at the different scenarios
SQL Fiddle DEMO
Use a LEFT join rather than INNER
For example:
SELECT * FROM `table1`
LEFT JOIN `table2` ON table1.messageid=table2.messageid
WHERE `venue_active` = 1
Either you need a LEFT JOIN instead, or
a FULL OUTER JOIN workaround for MySQL:
SELECT
a.*,
b.*
FROM
table1 a
LEFT JOIN
table2 b ON a.messageid = b.messageid
WHERE a.venue_active = 1
UNION
SELECT
a.*,
b.*
FROM
table1 a
RIGHT JOIN
table2 b ON a.messageid = b.messageid;
WHERE a.venue_active = 1

Multiple select statements in one query

I can do the following in 2 queries but want to make it simpler. Can this be combined in one query? If so how more efficient is it than doing two queries vs one?
query1: SELECT page_id, coupon_id from table_1 WHERE key = :key
query2: SELECT folder from table_2 WHERE page_id = table_1.page_id
For my final result I need to have a coupon_id from table_1, and a folder from table_2.
In query2 I need to use the page_id result from query1 to get the folder
Is there a simpler way to do this?
Use JOIN (LEFT, RIGHT or INNER is up to your needs):
SELECT
t1.page_id,
t1.coupon_id,
t2.folder
FROM
table_1 AS t1
LEFT JOIN table_2 AS t2 ON
t2.page_id = t1.page_id
WHERE
t1.key = :key
You will want to JOIN the tables on the page_id:
SELECT t1.page_id,
t1.coupon_id,
t2.folder
from table_1 t1
inner join table_2 t2
on t1.page_id = t2.page_id
WHERE key = :key
If you need help learning join syntax, here is a great visual explanation of joins.
I used an INNER JOIN which will return all rows that match between the two tables. If you want to return all rows from table_1
even if it doesn't have a matching row in table_2, then you would use a LEFT JOIN
SELECT
table_1.coupon_id AS coupon_id,
table_2.folder AS folder
FROM
table_1
INNER JOIN table_2 ON table_2.page_id = table_1.page_id
WHERE
table_1.key = :key
SELECT t1.page_id, t1.coupon_id, t2.folder
FROM table_1 t1 LEFT JOIN table_2 t2 ON (t1.page_id = t2.page_id)
WHERE t1.key = :key
This will be faster than two queries, how much depends on your data.
Try this please:
SELECT a.page_id, a.coupon_id, b.folder_id
from table_1 a
join table_2 b
ON a.page_id = b.page_id
WHERE a.key = :key
group by a.page_id
;

Getting the maximum value from interrelated MySQL tables

I am trying to unify a pair of queries with a LEFT JOIN, so that I can perform an ORDER BY on a desired column.
Table A has an exclusive one-to-many relationship with Table B, and table B has an exclusive one-to-many relationship with Table C.
I want to get the maximum value of a column in Table C, for each row in Table A.
what I used to have was:
$tableA = SELECT * FROM tableA;
for each row in $tableA {
$maxValue = SELECT MAX(value) FROM tableC WHERE tableB_id IN (SELECT tableB_id FROM tableB WHERE tableA_id={$row['tableA_id']}) GROUP BY tableB_id;
}
and now I'm thinking along the lines of:
SELECT * FROM tableA LEFT JOIN (SELECT tableA_id, MAX(max_c_value) FROM (SELECT tableB_id, MAX(value) max_c_value FROM tableC GROUP BY tableB_id) t GROUP BY tableA_id) USING(tableA_id)
but I know that's gibberish. I am not sure where to go from here.
I'm finding it hard to explain the problem, sorry.
SELECT A.ID, MAX(C.MyField) as CField
FROM A
LEFT OUTER JOIN B
ON A.ID = B.A_ID
LEFT OUTER JOIN C
ON B.ID = C.B_ID
GROUP BY A.ID
You will get null value for CField if there is no rows corresponding.
select max(table3.field),table1.field from table1
join table2 on table1.id=table2.table1_id
join table3 on table2.id = table3.table2_id
group by table1.field
You were closer on the first try I think. You want something like this:
SELECT MAX(tableC.cValue) FROM tableA
LEFT JOIN tableB
ON tableA.tableA_id = tableB.tableA_id
LEFT JOIN tableC
ON tableB.tableB_id = tableC.tableB_id
http://www.w3schools.com/sql/sql_join.asp
I have managed to solve it on my own, only to come back here and find I was making things far too complicated for myself, getting lost in a sea of tables!
This code did actually work, but I have already replaced it with the simpler code suggested above:
SELECT * FROM A LEFT JOIN (
SELECT A_ID, MAX(val) FROM (
SELECT * FROM B LEFT JOIN (
SELECT B_ID, MAX(val) val FROM C GROUP BY B_ID
) x USING(B_ID)
) y GROUP BY A_ID
) z USING(A_ID);

MySQL Select Count with EXISTS

I have 3 tables.
table1
id, thing_id
table_index
id
table_index_info
table_index_id, table1_id
table_index_info contains a history of table_index. This history can refer to table1, possibly many times or 0 times.
I need to run a query that returns all rows in table1 with a specific thing_id.
It also needs to count how many rows in table_index that have at least 1 table_index_info linking to table1.
Here's my query:
SELECT table1.*,
(SELECT COUNT(i.id)
FROM table_index i
WHERE EXISTS (SELECT 0
FROM table_index_info h
WHERE h.table1_id = table1.id
AND h.table_index_id = i.id)
) AS indexCount
FROM table1
WHERE table1.thing_id= $thingId
Is this the best/correct way to do this?
I would use a JOIN instead of EXISTS in this case.
SELECT table1.*,
( SELECT COUNT(i.id)
FROM table_index i
INNER JOIN table_index_info h ON h.table_index_id = i.id
WHERE h.table1_id = table1.id
) AS indexCount
FROM table1
WHERE table1.thing_id = $thingId

Categories