SQL add rows count from a second table to the main query - mysql

I'm trying to improve a (not so much) simple query:
I need to retrieve every row from Table A.
Then join Table A with Table B so I get all the data I need.
At the same time, I need to add an extra column with the count() from Table C.
Something like:
SELECT a.*,
(SELECT Count(*)
FROM table_c c
WHERE c.a_id = a.id) AS counter,
b.*
FROM table_a a
LEFT JOIN table_b b
ON b.a_id = a.id
This works, ok, but in reality, I'm just making 2 queries and I need to improve this so it only do one (if, its even possible).
Anyone knows how can I achive that?

The simplest approach is likely to just move the correlated sub-query into a sub-query.
NOTE: Many optimisers deal with correlated sub-queries extremely effectively. Your example query could be perfectly reasonable.
SELECT
a.*,
b.*,
c.row_count
FROM
table_a a
LEFT JOIN
table_b b
ON b.a_id = a.id
LEFT JOIN
(
SELECT
a_id,
Count(*) row_count
FROM
table_c
GROUP BY
a_id
)
c
ON c.a_id = a.id
Another Note: SQL is an expression, it is not executed directly, it is translated into a plan using nest loops, hash joins, etc. Do not assume that having two queries is a bad thing. In this case my example may significantly minimise the number of reads compared to a single query and then use of GROUP BY and COUNT(DISTINCT).

Try this:
SELECT
tmp.*,
SUM(IF(c.a_id IS NULL,0,1)) as counter,
FROM (
SELECT
a.id as aid,
b.id as bid,
a.*,
b.*
FROM
table_a a
LEFT JOIN table_b b
ON b.a_id = a.id
) as tmp
LEFT JOIN table_c c
ON c.a_id = tmp.id
GROUP BY
tmp.aid,
tmp.bid

Related

Is it a bad action to use Dependent Query inside a Query with LIMIT 1?

I read a lot that using Dependent Query is bad and i should use JOINs, I have a code which JOINs a lot of tables together, like the following
SELECT a.a, b.b, c.c, d.d FROM
tablea a
JOIN tableb b ON a.id = b.id
JOIN tablec c ON a.id = c.id
JOIN tabled d ON a.id = d.id
WHERE a.id = 1
LIMIT 1
Right now i can use a Dependent Query and Select a value from another table with thea.a like this
SELECT a.a, b.b, c.c, d.d, (SELECT e FROM tablee WHERE id = a.a) AS e FROM
tablea a
JOIN tableb b ON a.id = b.id
JOIN tablec c ON a.id = c.id
JOIN tabled d ON a.id = d.id
WHERE a.id = 1
LIMIT 1
In this case, Do i use the easiest to read and edit for me Dependent Query, Or do i just stick with JOINs?
I read a lot that using Dependent Query is bad and i should use JOINs,
This is misguidance. Certainly, JOINs are very powerful and should not be discouraged. The SQL optimizer understands JOINs and they are quite powerful and easy to read.
The does not mean the correlated subqueries are wrong. For instance, yours is fine -- even from a performance perspective -- if you have an index on tablee(id, e). In fact, that might be the most optimal way of writing the query. Writing the query with a join would probably generate a similar execution plan, though.
If you did use a join, you would need a left join for the same semantics.
There are some situations where correlated subqueries are better in terms of performance. The exact specifics might vary by database, so there are no rules that are "general" across all databases.
My one very strong piece of advice is to qualify all column names when you reference more than on table in a query. So, you should be writing:
SELECT a.a, b.b, c.c, d.d,
(SELECT e.e FROM tablee e WHERE e.id = a.a) AS e
FROM tablea a . . .

LEFT JOIN with a dataset that might or might not exist

I'm trying to JOIN a Master Dataset, via a left join with 2 other Datasets, all of them have the same Key field. So nothing special there.
One of those secondary Datasets is the result of another Query and therefor might or might not exist. Obviously my JOIN statement fails when this table doesn't exist.
Below a really simplified version of the code, the JOIN is used to exclude rows from the table_a that exist in table b or c (if they exist).
SELECT a.id, a.name
FROM table_a a
LEFT JOIN table_b b
ON a.id = b.id
LEFT JOIN table c c
ON a.id = c.id
WHERE b.id IS NULL
AND c.id IS NULL;
I am not sure that I understand your question well, but I think that you should better do:
SELECT a.id,a.name
FROM table_a a
WHERE a.id NOT IN
(SELECT id FROM table_b)
AND a.id NOT IN
(SELECT id FROM table_c)
Any query optimizer should have the exact same performance with this request, and I find it much more readable.

Cardinality violation when using a subquery that returns two values

I have create a sql query that the sketch is like this
select *
from A
where A.id in (select B.id1, B.id2 from B);
where the main select returns those values for which A.id coincides with either B.id1 or B.id2.
Clearly this solution doesn't work as the cardinality doesn't match in the where clause. How can I overcome this problem?
One solution would be to make two sub-queries, one for B.id1 and one for B.id2, but as my sub-query is much longer than in this example I was looking for a more elegant solution.
I'm using Mysql
EDIT 1
As long as the syntax is simpler than using two sub-queries I have no issues using joins
EDIT 2
Thanks #NullSoulException. I tried the first solution and works as expected!!
Something like the below should do the trick.
select *
From table1 a , (select id1 , id2 from table2 ) b
where (a.id = b.id1) or (a.id = b.id2)
or you can JOIN with the same table twice by giving the joined tables an alias.
select * from table1 a
INNER JOIN table2 b1 on a.id = b1.id1
INNER JOIN table2 b2 on a.id = b2.id2
Please test the above against your datasets/tables..

MySQL IN clause query

Simply, I want to find a solution for testing if one column value exits within another, or not, across tables. I've naturally jumped to 'NOT IN clause' but I've also discovered I can't use a colum name within the bracket (b.full_name)
SELECT
*
FROM
tbl1_name a
INNER JOIN
tbl2_name
ON a.id = b.id
WHERE
a.name NOT IN (b.full_name);
What clause can I use to achieve what I'm looking for etc.
You could simply do
SELECT * FROM tbl1_name a
INNER JOIN tbl2_name ON a.id = b.id
WHERE a.name <> b.full_name;
The IN keyword is normally used to check for multiple values example
NOT IN ('A', 'B');
Or
NOT IN (subquery);
You can use subquery after not in clause and select all the names from the table b. Hope it will resolve your problem.
Select * from table1 a inner join table2 b
on a.id=b.id
where a.name not in
(Select names from table2)
you can perform that using subqueries, this way :
SELECT * FROM tbl1_name a
WHERE a.name IN (SELECT b.full_name FROM tbl2_name b WHERE a.id = b.id);

Select records from one table where a column value exists in another table

I have 2 MySQL tables A and B.
I would like to select only the records from B where a certain value exists in A.
Example:
A has columns: aID, Name
B has columns: bID, aID, Name
I just want the records from B for which aID exists in A.
Many thanks.
You need to do either INNER JOIN - records that exists in both tables, or use LEFT join, to show records that exists in A and matching IDs exists in B
A good reference:
You need to make a join, and if you don't want to retrieve anything from table b, just return values from table a.
This should work
select b.* from b join a on b.aID=a.aID
Below query will also work and will be effective
SELECT * FROM B
WHERE B.aID IN (SELECT DISTINCT aID FROM A)
You just need a simple inner join between tables A and B. Since they are related on the aID column, you can use that to join them together:
SELECT b.*
FROM tableB b
JOIN tableA a ON a.aID = b.aID;
This will only select rows in which the aID value from tableB exists in tableA. If there is no connection, the rows can't be included in the join.
While I recommend using a join, you can also replace it with a subquery, like this:
SELECT *
FROM tableB
WHERE aID NOT IN (SELECT aID FROM tableA)
You can use join like this.
Select b.col1,b.col2... From tableB b inner join table tableA a on b.field = a.field
Have you tried using a LEFT JOIN?
SELECT b.* FROM tableB b LEFT JOIN tableA a ON b.aID = a.aID