MySQL Select Count with EXISTS - php

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

Related

How to Avoid SubQuery with same output in MySql

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).

Trouble with syntax for SELECT in MySQL

I have tried the following syntax, which seems to work fine on SQL when I use Oracle SQL Developer. However, when I use the code in MySQL, I get ther error "Something went wrong!".
$result = mysqli_query($con, "SELECT * FROM Table1 NATURAL JOIN (SELECT ID, SUM(row2) FROM table2 GROUP BY ID) NATURAL JOIN (SELECT ID, COUNT(col1) FROM Table2 WHERE ID IS NOT NULL GROUP BY ID)")
or die("Something went wrong!");
Is there a difference in syntax in this case, or could it be anything else I'm doing wrong?
Thanks!
This is your query:
SELECT *
FROM Table1 NATURAL JOIN
(SELECT ID, SUM(row2) FROM table2 GROUP BY ID) NATURAL JOIN
(SELECT ID, COUNT(col1) FROM Table2 WHERE ID IS NOT NULL GROUP BY ID)
MySQL supports NATURAL JOIN (I don't recommend using it, but that is another matter). Unlike Oracle, you need to have table aliases on the tables, essentially names for them. You may also need column aliases. I always use them, so I don't know if they are needed.
Try this:
SELECT *
FROM Table1 t1 NATURAL JOIN
(SELECT ID, SUM(row2) as cnt_row2
FROM table2
GROUP BY ID
) t2row NATURAL JOIN
(SELECT ID, COUNT(col1) as cnt_col1
FROM Table2
WHERE ID IS NOT NULL
GROUP BY ID
) t2col1
You can actually simplify this query:
SELECT t1.*, t2.cnt_col1, t2.cnt_row2
FROM Table1 t1 INNER JOIN
(SELECT ID, COUNT(col1) as cnt_col1, SUM(row2) as cnt_row2
FROM Table2
GROUP BY ID
) t2
ON t1.id = t2.id
The filtering on ID IS NOT NULL has no effect, because a NULL value will not be included in the join.
In MySQL all the Sub queries that are used in the FROM part need an alias name. In your case its missing. And I don't use NATURAL JOIN because using other specific INNER JOIN or LEFT JOIN clarifies the condition and scenario. So may be you could rewrite your query like this to make it work:
SELECT * FROM Table1
INNER JOIN (SELECT ID, SUM(row2) FROM table2 GROUP BY ID) a
ON a.ID = Table1.ID
INNER JOIN (SELECT ID, COUNT(col1) FROM Table2 WHERE ID IS NOT NULL GROUP BY ID) b
ON b.ID = Table2.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

Select unmatched records from two tables of MYSQL

I have two tables Table1 and Table2 with some records
id is the common column in both tables and primarykey is set to this column in table1
There are many records in table1 and some of these records (not all) are updated into table2.
Now I want retrieve from table1 the records not updated into the table2.
For example in table1 there are records 1,2,3,4,5,6,7,8,9
And in table2 there are 3,4,7,9
Now How can I retrieve these records form table1 1,2,5,6 those not updated into table2
I wrote this query :
SELECT Table1.id, Table1.DATE, Table1.C_NAME, Table1.B_NAME
FROM [Table1] INNER JOIN Table2 ON Table1.SLIPNO <>Table2.id;
But the expected result not coming. This query lists all the records repeating each one record manytimes
Can any body give me solution to get the expected result.
select *
from table1
where table1.slip_no NOT IN (select id from table2)
Assuming name of common column is id
Or you can modify your query as
SELECT distinct (Table1.id, Table1.DATE, Table1.C_NAME, Table1.B_NAME)
FROM [Table1]
INNER JOIN Table2 ON Table1.SLIPNO <>Table2.id
A good reference on SQL joins
SELECT t1.*
FROM table1 AS t1
LEFT OUTER JOIN table2 AS t2 USING(id)
WHERE
t2.id IS NULL;
You can use the NOT IN operator on a subquery for table2.
Alternatively, use MINUS with two regular queries listing the ids in each table:
SELECT id FROM table1
MINUS
SELECT id FROM table2;
Try this
SELECT Table1.id, Table1.DATE, Table1.C_NAME, Table1.B_NAME FROM [Table1]
WHERE
NOT EXISTS (SELECT * from Table2 WHERE Table1.SLIPNO !=Table2.id );
You can use the following query
SELECT id FROM database1.table WHERE id NOT IN(SELECT id FROM database2.table)
SELECT child_table.id FROM child_table LEFT JOIN parent_table ON child_table.parent_id = parent_table.id WHERE parent_table.id IS NULL
This left join query returns all the records of the child_table when there is no match in the parent_table. When there is no match, all parent_table fields will be NULL.
inner join will not help. To get unmatched records I tried this:
SELECT
A.ID,A.DATE,A.NAME
FROM TABLE1 A
WHERE CONCAT(A.ID , A.DATE ,A.NAME)
NOT IN
(SELECT CONCAT(B.ID , B.DATE ,B.NAME) as X
from TABLE2 B) ;

How to Remove matching rows From mysql Join Result and show non-matching rows?

Is there any way to remove the matching rows from MySQL join Query.
Actually I have two tables where I have store the pub_id, and post_id in both tables these are common.
I want a result when I query all the matching rows from table1 and table2 should not be listed and the non-matching rows should be listed only.
Query return rows which exists only in one of two tables:
SELECT *
FROM Table1 t1
WHERE NOT EXISTS (Select 1 from Table2 t2
Where t1.pub_id = t2.pub_id
AND t1.post_Id = t2.post_id)
UNION ALL
SELECT *
FROM Table2 t1
WHERE NOT EXISTS (Select 1 from Table1 t2
Where t1.pub_id = t2.pub_id
AND t1.post_Id = t2.post_id)
you need something like that:
SELECT * FROM tablea AS a
RIGHT JOIN tableb AS o ON a.id = o.id WHERE a.pub_id IS NULL and a.post_id is null
UNION
SELECT * FROM tablea AS a
LEFT JOIN tableb AS o ON a.id = o.id WHERE o.pub_id IS NULL and o.post_id is null

Categories