Only show instances that equal the max value in temp table - mysql

I'm trying to create a new table with only the sname's that equal the maximum number of num_courses which is a column in a temporary table n.
SELECT s.sname, n.num_courses
FROM (SELECT e.sid, COUNT(distinct e.cno) as num_courses
FROM enroll e
GROUP BY e.sid) n, student s
WHERE s.sid = n.sid AND n.num_courses = (SELECT MAX(n.num_course) from n) x;
Is it possible to only show instances that equal the max value found in a temporary table? (Referring to the second WHERE clause on the last line)
This is the error:
ERROR 1064 (42000) at line 1 in file: 'q7.sql': You have an error in your
SQL syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'x' at line 5
It says the error is at line 1 but when I remove the last clause on the last line, there's no error.

You can't reuse the subquery like that. You'll need to write the query again in the where clause.
I think you intended to do this:
select s.sname,
n.num_courses
from (
select e.sid,
COUNT(distinct e.cno) as num_courses
from enroll e
group by e.sid
) n,
student s
where s.sid = n.sid
and n.num_courses = (
select MAX(n.num_course)
from (
select COUNT(distinct e.cno) as num_courses
from enroll e
group by e.sid
) t
);

You don't need x tablename and you can't use the n table alias but you need all the code
SELECT s.sname, n.num_courses
FROM (SELECT e.sid, COUNT(distinct e.cno) as num_courses
FROM enroll e
GROUP BY e.sid) n
INNER JOIN student s ON s.sid = n.sid AND (SELECT MAX(n.num_course) from
( SELECT e.sid, COUNT(distinct e.cno) as num_courses
FROM enroll e
GROUP BY e.sid) n )

You don't need that alias in WHERE condition and also try using IN instead since MAX() could return multiple result like
n.num_courses IN (SELECT MAX(n.num_course) from n);

Related

MySQL error #1111 - Invalid use of group function

Yes, this is an assignment. So the task was to output two columns of 'first name' and 'last name' with conditions:
-A u (B ∩ -C ∩ -(A ∩ -( B u D)))
A: All consumers that didn't shop on Monday and Friday
(time_by_day.the_day)
B: All consumers who bought 'Non-Consumable'
(product_class.product_family)
C: All consumers who bought more than 10 items
(sales_fact_1997.unit_sales) at one time (sales_fact_1997.time_id)
D: Female consumers from Canada (consumer.gender, consumer.country)
This is what I got so far
SELECT
c.fname,
c.lname
FROM
customer AS c
INNER JOIN sales_fact_1997 AS s ON c.customer_id = s.customer_id
INNER JOIN time_by_day AS t ON s.time_id = t.time_id
INNER JOIN product AS p ON s.product_id = p.product_id
INNER JOIN product_class AS pc ON p.product_class_id = pc.product_class_id
Where
NOT t.the_day in ('Monday', 'Friday') OR
(
pc.product_family = 'Non-Consumable' AND
NOT SUM(s.unit_sales) > 10 AND
NOT (
t.the_day in ('Monday', 'Friday') AND
NOT (
pc.product_family = 'Non-Consumable' OR
(c.country = 'Canada' AND c.gender = 'F')
)
)
)
GROUP BY concat(c.customer_id, s.time_id)
That ended up with an error
#1111 - Invalid use of group function
But I don't know which part of the code is wrong. I'm pretty sure that it's probably the WHERE part. But I don't know what I did wrong.
Condition C is where I'm really struggling. I manage just fine making a query of C
SELECT
t.time_id,
c.customer_id,
c.fullname,
round(SUM(s.unit_sales),0) as tot
FROM
customer as c
INNER JOIN sales_fact_1997 as s ON c.customer_id = s.customer_id
INNER JOIN time_by_day as t on s.time_id=t.time_id
GROUP BY concat(c.customer_id, s.time_id)
ORDER BY c.customer_id, t.time_id
But trying to incorporate it into the main code is hard for me.
Reading online I assume that I should probably use HAVING instead of WHERE.
I would really appreciate it if someone can point me in the right direction.
This is the database that I used.
C: All consumers who bought more than 10 items
(sales_fact_1997.unit_sales) at one time (sales_fact_1997.time_id)
You should use COUNT not SUM.
SELECT time_id,
count(*)
FROM sales_fact_1997
GROUP BY time_id
HAVING COUNT(*)>=10 ;
count(*) is not needed, I let just to show the results
Can you try if it helps:
SELECT c.lname,
c.fname
FROM customer c
INNER JOIN
(
SELECT time_id,customer_id,product_id
FROM sales_fact_1997
GROUP BY time_id,customer_id,product_id
HAVING COUNT(*)>=10
) as s on c.customer_id=s.customer_id
INNER JOIN
(
SELECT time_id,the_day
FROM time_by_day
WHERE the_day
NOT IN ('Monday','Friday')
) as t on s.time_id=t.time_id
INNER JOIN
(
SELECT product_family,product_id
FROM product_class
INNER JOIN product
on product_class.product_class_id=product.product_class_id
WHERE product_family='Non-Consumable'
) pc on s.product_id=pc.product_id
where c.country='Canada' and c.gender ='F' ;

UPDATE VALUE IN MYSQL MARIA DB WITH JOIN

I am trying to change the value of a column table with a sum function, this is my code:
For example
c.total = (10-2-3) - (3)
c.total = 2
update tabC c
JOIN tabB b ON b.c_id = c.id
set c.total = (c.v1 - c.v2 - c.v3) - IF(sum(b.payment) is not null, sum(b.payment), 0)
where c.id= 983;
but I get the following error:
ERROR 1111 (HY000): Invalid use of group function
I think the error is sum, but how can I solve that?
Thanls in advance
You need to join with a subquery that uses GROUP BY.
UPDATE tabC c
LEFT JOIN (
SELECT c_id, SUM(payment) AS total_payment
FROM tabB
GROUP BY c_id) AS b ON b.c_id = c.id
SET c.total = (c.v1 - c.v2 - c.v3) - IFNULL(b.total_payment, 0)
WHERE c.id = 983
You should usee a nested subquery whit aggregated resutl for join
update tabC c
JOIN (
select c_id, ifnull(sum(payment),0) tot_payment
from tabB
group by c_id
) b ON b.c_id = c.id
set c.total = (c.v1 - c.v2 - c.v3) - b.tot_payment
where c.id= 983;

Cannot access field multiple sub queries deep

I'm getting an error trying to access a selected field in a sub query of a sub query. It says “Unkown column in where clause”. I have other sub queries as well using that same field and they work perfectly. The problem only seems to occur when I try to access the field in sub query within a subquery.
The simplified version of my query
SELECT r.id,
(SELECT min(begindatum)
FROM ((SELECT begindatum FROM reservatiekamer
WHERE reservatieId = r.id) UNION
(SELECT begindatum FROM reservatiefaciliteit
WHERE reservatieId = r.id)) as bg)
as begindatum
FROM reservatie r
The error
#1054 - Unknown column 'r.id' in 'where clause'
The background story, I'm trying to select the start date of a reservation that exists of multiple reservations of rooms and facilities (2 different tables).
If the subqueries always return exactly one value, you can use least():
SELECT r.id,
least((SELECT begindatum FROM reservatiekamer WHERE reservatieId = r.id),
(SELECT begindatum FROM reservatiefaciliteit WHERE reservatieId = r.id)
) as begindatum
FROM reservatie r;
Actually, this variation will work better:
SELECT r.id,
least(COALESCE((SELECT MIN(begindatum) FROM reservatiekamer WHERE reservatieId = r.id), 0),
COALESCE((SELECT MIN(begindatum) FROM reservatiefaciliteit WHERE reservatieId = r.id), 0)
) as begindatum
FROM reservatie r;
This assumes that the values are always positive, which is why the 0 is there. Another value might be more appropriate.
Finally, you can move the logic to the from clause:
SELECT r.id,
LEAST(COALESCE(rk.minbd, rf.minbd), COALESCE(rf.minbd, rk.minbd)) as begindatum
FROM reservatie r LEFT JOIN
(SELECT reservatieId, MIN(begindatum) as minbd
FROM reservatiekamer
GROUP BY reservatieId
) rk
ON r.id = rk.reservatieId LEFT JOIN
(SELECT reservatieId, MIN(begindatum) as minbd
FROM reservatiefaciliteit
GROUP BY reservatieId
) rf
ON r.id = rf.reservatieId;
The coalesce() is the least() is intended to return one value if the other is NULL.

Trying to add one last SUM() column to my query in SQL Server 2008

I have the first query which is producing correct results. What I need is I need to add the sum of values as a last column grouped by surveyid. I can't insert Sum(c.value) into the first query because it is an aggregate function. I have the correct query as my second query below. I know there's pivot functionality but not sure if it can be used here. I do realize that there will be repetition but that's okay.
'first query
SELECT
A.PATIENTID, B.STUDENTNUMBER, c.surveyid,
convert(varchar, A.CreatedDate, 107),
C.QuestionID, C.Value, D.Question
FROM
dbo.Survey A, dbo.Patient B, [dbo].[SurveyQuestionAnswer] C, [dbo].[LookupQuestions] D
WHERE
A.PATIENTID = B.ID
and c.SurveyID = A.ID
and c.QuestionID = d.ID
and c.questionid <> 10
ORDER BY
A.PATIENTID
'second query
select
c.surveyid,SUM(c.value) as scores
from
dbo.SurveyQuestionAnswer c
group by
c.SurveyID
order by
SurveyID '---not important
You can use SUM if you add the OVER clause. In this case:
SELECT
A.PATIENTID, B.STUDENTNUMBER, c.surveyid,
convert(varchar, A.CreatedDate, 107),
C.QuestionID, C.Value, D.Question,
SUM(c.Value) OVER(PARTITION BY c.surveyid) scores
FROM
dbo.Survey A
INNER JOIN dbo.Patient B
ON A.PATIENTID = B.ID
INNER JOIN [dbo].[SurveyQuestionAnswer] C
ON c.SurveyID = A.ID
INNER JOIN [dbo].[LookupQuestions] D
ON c.QuestionID = d.ID
WHERE
c.questionid <> 10
ORDER BY
A.PATIENTID
You could use something like this:
SELECT
s.PATIENTID, p.STUDENTNUMBER, sqa.surveyid,
CONVERT(varchar, s.CreatedDate, 107),
sqa.QuestionID, sqa.Value, lq.Question,
Scores = (SELECT SUM(Value) FROM dbo.SurveyQuestionAnswer s2 WHERE s2.SurveyID = s.ID)
FROM
dbo.Survey s
INNER JOIN
dbo.Patient p ON s.PatientID = p.ID
INNER JOIN
[dbo].[SurveyQuestionAnswer] sqa ON sqa.SurveyID = s.ID
INNER JOIN
[dbo].[LookupQuestions] lq ON sqa.QuestionID = lq.ID
WHERE
sqa.questionid <> 10
ORDER BY
s.PATIENTID
By having a subquery with the SUM(...) you should be able to get that sum as a single value and you don't need to use any grouping function

Joining two tables in SQL

I have two tables that share the same column (C) but SQL tells me I have an error
Here is the first table from the first query:
SELECT E.C AS C,
COUNT(C) AS CC
FROM E
GROUP BY E.C
And here is the second query:
SELECT E.C AS C,
COUNT(C) AS Num
FROM E, G
WHERE E.G = G.L
AND G.G <
(SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C
So I tried to simply put these two together by putting JOIN in between them. But this doesn't join them, even though they share the same column C. It simply says I have a syntax error. What is wrong? And how do I fix it? I have confirmed that when run separately, they produce the correct output with a column C
Below is the total JOIN execution
(SELECT E.C AS C,
COUNT(C) AS CC
FROM E
GROUP BY E.C)
JOIN
(SELECT E.C AS C,
COUNT(C) AS Num
FROM E, G
WHERE E.G = G.L
AND G.G <
(SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C)
And the error is
Error code 1064, SQL state 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'JOIN
(SELECT E.C AS C,
COUNT(C) AS Num' at line 6
Line 1, column 1
You did not show your syntax error but, I am guessing your has to do with the following line:
COUNT(C) AS CC
Since both tables have a column C, the query does not know which table to return the value from. You need to preface it with the table name or alias.
This line works in your first query because you only had one column called C, once you have two you need to specify which one you want to return.
Based on your edit, you are missing aliases for the subqueries and the on condition for the join:
select t1.C, t1.cc, t2.num
from
(
SELECT E.C AS C,
COUNT(C) AS CC
FROM E
GROUP BY E.C
) t1 -- added alias
INNER JOIN
(
SELECT E.C AS C,
COUNT(E.C) AS Num -- added table name, since column c exists in both tables
FROM E
JOIN G
ON E.G = G.L
WHERE G.G < (SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C
) t2 -- added alias
on t1.C = t2.C -- added on clause
Try this:
select Z.C /*other*/
from (SELECT E.C AS C,
COUNT(E.C) AS CC
FROM E
GROUP BY E.C) Z
JOIN (SELECT E.C AS C,
COUNT(E.C) AS Num
FROM E, G
WHERE E.G = G.L
AND G.G < (SELECT min(G.G)
FROM G
WHERE G.L = "BLAH")
GROUP BY E.C) Y on Y.C = Z.C