create mysql subquery with joins where count equals zero - mysql

I am trying to get results where CountId equals zero. I tired the code below but does not work.Can someone please please help :)
SELECT table1.id,table1.name2,table1.name3,table1.name4,table1.name, COUNT(table2.id ) AS CountId
from table1
LEFT JOIN table2
ON table1.name4 = table2.name4
AND table1.name3 = table2.name3
AND table1.name2 = table2.name2
WHERE CountId = 0

You cannot use an aggregate function (such as SUM,COUNT,etc) in WHERE clause.
Use HAVING clause after GROUP BY. Also it is a good practice to use alias names when you join multiple tables.
SELECT t1.id,t1.name2,t1.name3,t1.name4,t1.name, COUNT(t2.id) AS CountId
from table1 t1
LEFT JOIN table2 t2 ON t1.name4 = t2.name4
AND t1.name3 = t2.name3
AND t1.name2 = t2.name2
GROUP BY t1.id,t1.name2,t1.name3,t1.name4,t1.name
HAVING COUNT(t2.id) = 0

Related

avoid subquery by using "join" and "group by"

I'm trying to avoid a subquery but I'm not able to get the right result:
This is the original query:
SELECT T1.IdL, T1.REG, T1.YearIn, T1.URL,
(SELECT Count(*) FROM T2 WHERE T1.IdL = T2.IdL) AS IdL_Count
FROM T1
The following is an attempt to avoid subquery but doesn't works becouse the rows where there aren't records in T2 are missing
SELECT T1.IdL, T1.REG, T1.YearIn, T1.URL, Count(*) AS IdL_Count
FROM T1 INNER JOIN T2 USING(IdL)
GROUP BY IdL
So I tryed LEFT JOIN but I get wrong IdL_Count: 1 instead of 0
Is there a way to avoid subquery or not?
There is no way to avoid sub query, at least without specified tables structure (indexes etc).
But this query should perform much better
SELECT T1.IdL, T1.REG, T1.YearIn, T1.URL, coalesce(T3.count, 0) AS IdL_Count
FROM T1
LEFT JOIN (SELECT IdL, count(*) as count FROM T2 GROUP BY IdL) T3 on T3.IdL = T1.IdL
I think if you make the COUNT(T2.[somefield]), instead of COUNT(*), it will return 0 when expected. If that does not work, you can do SUM(IF(T2.IdL IS NULL, 0, 1)) AS IdL_Count instead.

Sum the same value with different condition

Ok, the title is cryptic but I don't know how to sintetize it better.
I have a series of expensive similar SELECT SUM queries that must be executed in sequence.
Example:
SELECT SUM(t2.Field)
FROM Table1 AS t1
INNER JOIN (
SELECT Field FROM Table2
WHERE [list of where]
) AS t2 ON ti.ExtKey = t2.Key
WHERE t1.TheValue = 'Orange'
SELECT SUM(t2.Field)
FROM Table1 AS t1
INNER JOIN (
SELECT Field FROM Table2
WHERE [list of where]
) AS t2 ON ti.ExtKey = t2.Key
WHERE t1.TheValue = 'Apple'
And so on.
I've used the nested inner join because after some test it resulted faster than a plain Join.
The rows selected for Table2 are always the same, or at least the same for session.
There's a way to group all the queries in one to speed up the execution?
I was thinking about using a material view, but this would complicate very much the design and maintenance.
I am no sure about your goal. I have a guess for you:
http://sqlfiddle.com/#!9/af66e/2
http://sqlfiddle.com/#!9/af66e/1
SELECT
SUM(IF(t1.TheValue = 'Orange',t2.Field,0)) as oranges,
SUM(IF(t1.TheValue = 'Apple',t2.Field,0)) as apples
FROM Table1 AS t1
INNER JOIN (
SELECT Field, `key` FROM Table2
) AS t2 ON t1.ExtKey = t2.`key`
# GROUP BY t1.extkey uncomment if you need it
If you can provide raw data sample and expected result that would help a lot.
I think you want a group by:
SELECT t1.TheValue, SUM(t2.Field)
FROM Table1 t1 INNER JOIN
(SELECT Field
FROM Table2
WHERE [list of where]
) t2
ON t1.ExtKey = t2.Key
GROUP BY t1.theValue;
Note that your query doesn't quite make sense, because t2 doesn't have a column called key. I assume this is an oversight in the question.
If you want to limit it to particular values, then use a WHERE clause before the GROUP BY:
WHERE t1.TheValue IN ('Apple', 'Orange', 'Pear')

MySQL customized join query using multiple tables

I am searching one student from each class from one group. There are different class groups and every group has different classes and every class has multiple students. See below:
Group1 --> Class1, Class2 etc
Class1 --> GreenStudent1, GreenStudent2 etc
Class2 --> RedStudent1, RedStudent2 etc
------------------------------------------------------
SELECT
table1.id,
table1.myname,
table1.marks
table2.studentid,
table2.studentname
FROM table1
INNER JOIN table3 ON table1.oldid = table3.id
INNER JOIN table2 ON table2.studentid = table3.newid
WHERE
table1.classgroup = 'SCI79'
GROUP BY table1.oldid
ORDER BY table1.marks DESC
There are different joins applied in the query. Above mentioned query giving me correct results but I need little modification in it. Current query returning me one student from each class.
What I need? I need one student from each class but only that student who has MAXIMUM
table1.marks
So I should have one student from each class who has maximum number in their relevant classes. Can anyone suggest some solution or rewrite this query? Thanks :)
A subquery on an INNER JOIN should handle this:
SELECT t1.id
,t1.myname
,maxMarks.marks
,t2.studentid
,t2.studentname
FROM table1 t1
INNER JOIN table3 t3 ON t1.oldid = t3.id
INNER JOIN table2 t2 ON t2.studentid = t3.newid
INNER JOIN (
SELECT id
,MAX(marks) AS marks
FROM table1
GROUP BY id
) maxMarks ON t1.id = maxMarks.id
AND t1.marks = maxMarks.marks
WHERE t1.classgroup = 'SCI79'
GROUP BY t1.oldid
ORDER BY t1.marks DESC
Joining the aggregated table with MAX back on itself should filter down the result set to each student and their individual highest marks.
EDIT
I think I misread your original question ... you wanted students only that have the MAX(marks) period? in that case, use this query:
SELECT t1.id
,t1.myname
,t1.marks
,t2.studentid
,t2.studentname
FROM table1 t1
INNER JOIN table3 t3 ON t1.oldid = t3.id
INNER JOIN table2 t2 ON t2.studentid = t3.newid
WHERE t1.classgroup = 'SCI79'
AND t1.marks = (
SELECT MAX(marks) AS marks
FROM table1
)
GROUP BY t1.oldid
ORDER BY t1.marks DESC
This WHERE clause will only return students that have marks matching the MAX mark in the entire table.
You could use the max function, something like:
where table1.marks = max(table1.marks)

subquery that uses a value from the outer query in the where caluse

I wanna run a subquery that uses the value of the outer query in its where clause. Here's and example of what I wanna do:
SELECT * FROM `tbl1`
WHERE `tbl1`.`max_count` < (
SELECT COUNT(*) rc FROM `tbl2`
WHERE `tbl2`.`id` = `tbl1`.`id
)
There is tbl1 with a column named max_count, and there is tbl2 with rows referring to a row in tbl1(many-to-one relationship). What I wanna do is select rows in tbl1 where the number of rows in tbl2 referencing it is less than the max_count value of that row. But I'm pretty sure that what I wrote here, ain't gonna cut it. Any ideas?
Thanks a lot
try this -
SELECT * FROM `tbl1` t1
WHERE t1.`max_count` < (
SELECT COUNT(*) FROM `tbl2` t2
WHERE t2.`id` = t1.`id`
)
try using JOIN.
SELECT DISTINCT a.*
FROM tb1 a
INNER JOIN
(
SELECT id, COUNT(*) totalCount
FROM tbl2
GROUP BY id
) b ON a.ID = b.ID
WHERE a.max_count < b.totalCount
As an alternate solution, it's probably easier to just use a LEFT JOIN with HAVING than a subquery;
SELECT tbl1.*, COUNT(tbl2.id) current_count
FROM tbl1
LEFT JOIN tbl2
ON tbl1.id=tbl2.id
GROUP BY tbl1.id
HAVING COUNT(tbl2.id) < max_count
An SQLfiddle to test with.
Note that the GROUP BY in this case is a MySQL only thing, normally you'd need to GROUP BY every selected field in tbl1 even if tbl1.id is known to be unique per row.

Subquery error in MySQL with max()

I'm trying a subquery in MySQL using max(), and I keep running into an error. The gist of the query is below (though I've changed the field names).
select table1.field1, table1.field2, table2.field3, table2.field4, table3.field5,
(select max(age)
from age_table
where age_table.person = table2.person)
from table1
inner join table2 on table2.person = table1.person
inner join table3 on table3.person = table1.person
inner join age_table on age_table.person = table1.person
When I try this, I get a syntax error that points to
'from age_table where age_table.person=table2.person'
...but I can't figure out what the problem is.
Use table aliases to differentiate between tables, without having to use the full table name:
SELECT t1.field1, t1.field2, t2.field3, t2.field4, t3.field5,
(SELECT MAX(at.age)
FROM AGE_TABLE at
WHERE at.person = t2.person) AS max_age
FROM TABLE1 t1
JOIN TABLE2 t2 ON t2.person = t1.person
JOIN TABLE3 t3 ON t3.person = t1.person
I removed what appeared to be a redundant JOIN to the AGE_TABLE, seeing as it wasn't used in the SELECT clause.
It's also good habit to define a column alias for derived column values - makes them easier to reference. See "max_age" for an example.
You need to create an alias for your subquery eg:
(select max(age) from age_table where age_table.person = table2.person) temp
and leave rest of the things as they are.