SQL trouble with COUNT - mysql

I have some SQL code that returns me some data from DB
SELECT t1.id as id, title, description FROM table1 t1
JOIN table2 t2 ON t1.id = t2.t1_id
WHERE t2.t3_id IN( SELECT id FROM table3 WHERE parent_id IN ( SELECT id FROM table3 WHERE parent_id = 1)) GROUP BY t1.id
I have some problem with counting number of rows of result. I know that I have to write almost the same code but with COUNT but I have there A problem, my code doesn't return me a number of rows.

Just use the COUNT(*) function. Also, your subqueries can be converted to a JOIN (and your sub-subquery is redundant):
SELECT COUNT(*)
FROM table1 t1
JOIN table2 t2
ON t1.id = t2.t1_id
JOIN table3 t2
ON t3.id = t2.t3_id
WHERE t3.parent_id = 1

Related

Using values from main query inside a subquery

I had a problem creating a MySQL query with a subquery.
I wanted to use some data from the main query on the subquery, as many times did.
But this time I wanted to use it in a JOIN and didn't worked. I really want to understand why this happens.
I will show you some examples that works and the one that didn't.
I made this simple structure to reproduce the example:
# table1
id field1
1 *first_value*
2 *another_value*
#table2
id field2
1 *second_value*
Using table1.id on the WHERE of the subquery to get a value, the most typical use for me (I know this can be a join, but i try to show the difference):
SELECT
t1.field1,
(
select t2.field2
FROM table2 as t2
WHERE t2.id = t1.id
) as field2
FROM table1 as t1
WHERE t1.id = '1';
You can use table1.id on the SELECT part too (not much sense in the example, but works):
SELECT
t1.field1,
(
select t1.id as field2
FROM table2 as t2
WHERE t2.id = t1.id
) as field2
FROM table1 as t1
WHERE t1.id = '1';
Now, if you try to use it on a JOIN inside the subquery, then, crashes:
SELECT
t1.field1,
(
select t1.id
FROM table2 as t2
LEFT JOIN table1 as t3 ON t3.id = t1.id
WHERE t2.id = t1.id
) as field2
FROM table1 as t1
WHERE t1.id = '1';
Kernel error: Error( 1054 ) 42S22: "Unknown column 't1.id' in 'on clause'"
Buuut, u can do the JOIN using the field in another subquery changing ON t3.id = t1.id to ON t3.id = (SELECT t1.id) ???
SELECT
t1.field1,
(
select t1.id
FROM table2 as t2
LEFT JOIN table1 as t3 ON t3.id = (SELECT t1.id)
WHERE t2.id = t1.id
) as field2
FROM table1 as t1
WHERE t1.id = '1'
I wonder to know why the third example query doesn't work while all others does.
Can someone explain this, please?
Thank you :)
That's because all elements in the ON clause of a JOIN, must belong the one of the joined tables, so as your t2.id must be equal to t1.id, you can do
SELECT
t1.field1,
(
select t1.id
FROM table2 as t2
LEFT JOIN table1 as t3 ON t3.id = t2.id
WHERE t2.id = t1.id
) as field2
FROM table1 as t1
WHERE t1.id = '1';

How to LEFT JOIN table1 ON table2 WHERE table2 row fulfills certain conditions

Please consider this query:
SELECT table1.* ,
(SELECT quantity FROM table2 WHERE id = table1.id AND table2.location = 10) quantity,
(SELECT reorder_level FROM table2 WHERE id = table1.id AND table2.location = 10) reorder_level,
(SELECT stock_date FROM table2 WHERE id = table1.id AND table2.location = 10) stock_date
FROM table1
WHERE category_id = 5 ORDER BY table1.id;
The aliases quantity, location and stock_date are obviously referencing a a row in table2 that fulfill the condition: id=table1.id and location=10.
This query works, but is probably suboptimal as a result of the clumsy subqueries.
How can I best join table1 to table2 USING(id) but only on rows where location is also 10.
TIP: One row from table1 has many rows in table2.
Unfortunately, the actual table definitions are much more complex, and I reckoned it might be counter-productive to dump the entire thing on this thread.
You can use additional condition in ON() part so it will join only rows which fulfills the provided criteria
SELECT t1.* ,
t2.quantity ,
t2.reorder_level,
t2.stock_date
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id AND t2.location = 10
WHERE t1.category_id = 5
ORDER BY t1.id;
Another way would be use a subselect for your table2 and select only rows where location is equal to 10
SELECT t1.* ,
t2.quantity ,
t2.reorder_level,
t2.stock_date
FROM table1 t1
LEFT JOIN
(SELECT * FROM table2 WHERE t2.location = 10) t2
ON t1.id = t2.id
WHERE t1.category_id = 5
ORDER BY t1.id;

SQL Select When Something IS NOT IN a Joined Table

Ok. I have some data in one table, that references on multiple occasions some data in another table.
Table1 - main client table
Table2 - user defined fields
Say I have a query that shows a client id from Table1 and all attached / used "used defined fields" from Table2
SELECT t1.Id, t2.udf
FROM Table1 t1
JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t1.EndDate IS NULL AND
t1.Id = '1234.9876' AND
I would get the following for a result...
ID UDF
1234.9876 100
1234.9876 110
1234.9876 118
1234.9876 124
1234.9876 198
1234.9876 256
Now, say I wanted to query this same thing, and get ONLY the ID of the Client, but ONLY IF a value for t2.udf equaling '194' did not exist. So, I would simply get
ID
1234.9876
...as a result.
Make the join a LEFT join and filer where t2.Index is null
SELECT t1.Id
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.Id = t2.Index
AND t2.UDF = 194 -- has to be before where clause
WHERE t2.Index IS NULL
AND t1.EndDate IS NULL
AND t1.Id = '1234.9876' -- not sure if you want this part
Another way by using NOT EXISTS
SELECT t1.Id
FROM Table1 t1
WHERE NOT EXISTS (SELECT 1 FROM Table2 t2 WHERE t1.Id = t2.INDEX
AND t2.UDF = 194)
AND t1.EndDate IS NULL
AND t1.Id = '1234.9876'
See also JOINS
You can add AND t2.udf not in (select udf from table2 where udf <> '194').
But #SQLMenace solution is better
This should do it.
SELECT DISTINCT t1.Id
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t2.UDF NOT IN (194)
AND t2.Index IS NULL
Select DISTINCT gives you unique entries that satisfy the other conditions, and the first where clause
t2.UDF NOT IN (194)
Normall would return all the rows for the t1 where the t2.UDF is not 194, but it is limited by the Select Distinct to give you only distinct id's
Try the following:
SELECT t1.Id
FROM Table1 t1
JOIN Table2 t2 ON t1.Id = t2.Index
WHERE t1.EndDate IS NULL AND
t1.Id = '1234.9876' AND
t2.udf <> '194'

How to retrieve the not common values from 2 tables?

I have the 2 following tables t1, t2 with values,
t1 t2
1 4
2 2
3 3
Now I want to output
1
4
How can I get this output in select query ?
This will get you each item from t1 that is not present in t2, and each item in t2 that is not present in t1:
select t1.id from t1
left join t2 on t2.id = t1.id
where t2.id is null
union all
select t2.id from t2
left join t1 on t1.id = t2.id
where t1.id is null
(I have assumed that the field name in each table is named id just for the sake of being able to write a query against the tables.)
Another way would be:
select coalesce(t1.id, t2.id)
from t1
full outer join t2 on t2.id = t1.id
where t1.id is null or t2.id is null
Another way. Just COUNT them.
This works if the values are unique per table
SELECT
CombinedValue
FROM
(
SELECT t1 AS CombinedValue FROM t1
UNION ALL
SELECT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
If not unique per table
SELECT
CombinedValue
FROM
(
SELECT DISTINCT t1 AS CombinedValue FROM t1
UNION ALL
SELECT DISTINCT t2 FROM t2
) foo
GROUP BY
CombinedValue
HAVING
COUNT(*) = 1
you can use Joins in MySql to proceed and to obtain result.
this will help you
http://www.techrepublic.com/article/sql-basics-query-multiple-tables/1050307

MySQL Join and inner selects

I currently have a query
SELECT id FROM table1 WHERE {filters on table1} AND id NOT IN (SELECT table1ID FROM table2 WHERE condition = 0)
Table1 has a 1 - Many relationship with table2 and I'm looking for all the IDs that have no entries in table2 with condition=0.
Is there any way to rewrite this query without the inner select? I'm been scratching my head about it for a while now and any pointers would be welcome.
You can try something like
SELECT id
FROM table1 t1 LEFT JOIN
table2 t2 ON t1.ID = t2.table1ID
AND t2.Condition = 0
WHERE {filters on table1}
AND t2.table1ID IS NULL
Or just as good would be
SELECT id
FROM table1 t1
WHERE {filters on table1}
AND NOT EXISTS (
SELECT 1
FROM table2 t2
WHERE t1.ID = t2.table1ID
ADN t2.condition = 0
)