SQL Group By error ORA-00979 - sql

I'm trying to give this query:
select s_name, course from Student group by course;
But I get an error (ORA-00979 Not a GROUP BY EXPRESSION).
I want to list the names of all the students that are in the same course.
Is there another method of doing this? If not, what is the proper way to implement this query? I would appreciate if someone could give me the exact code required.

One variant (Oracle 11g):
select course, listagg(s_name, ', ') within group (order by s_name)
from student
group by course;
Oracle 10g (undocumented secret function wm_concat)
select course, wm_concat(s_name)
from student
group by course;

For what you want you shouldn't use GROUP BY.
The intention of GROUP BY is to summarise information per group.
Since you want detail within each course, you should rather use ORDER BY to ensure that your output is simply sorted with students in the same course listed together.
select s_name, course
from Student
order by course
For an example of what GROUP BY is intended for, try the following:
select course, COUNT(*) as NumStudents
from Student
group by course

Related

Trying to follow GROUP BY logic in SQL

I'm prepping for an SQL interview and was going over this guide.
The eventual code the author wrote was:
SELECT cust_id,
first_name,
sum(total_order_cost)
FROM customers
JOIN orders ON customers.id = orders.cust_id
GROUP BY cust_id,
first_name
MY QUESTION:
Why is first_name used in the GROUP_BY? If I wrote the code without first_name in the GROUP BY, I'm getting errors.
thanks in advance.
Unaggregated columns in the SELECT (cust_id and first_name in this case) need to be listed in the GROUP BY. Even in cases like this one, where there's (presumably) only one first_name per cust_id, the DB engine still expects every column in the SELECT to either be in an aggregate function or in the GROUP BY.

using count and group by correctly

I have a relation CandyC(id, email, age, name, candy_id)
I want to count the CandyC.ids associated with a CandyC.candy_id once.
Attempt:
SELECT email, age, name
FROM CandyC
GROUP BY id
HAVING COUNT(DISTINCT candy_id) = 1;
It gives me an error:
not a group by expression
The group by clause need to have all the non aggregated columns selected directly. Also, it's usually a good idea to use having after the group by as it's the standard way of writing this (even though Oracle supports it the other way too).
Does this do what you want:
select email, age, name
from candyc
group by id, email, age, name
having count(distinct candy_id) = 1
If not, you should provide sample data and expected results in your question to clarify.
I think you want something more like this:
SELECT candy_id, COUNT(*)
FROM CandyC
GROUP BY candy_id;
I don't know what the email/age/name columns have to do with the question:
I want to count the CandyC.ids associated with a CandyC.candy_id once.

Getting around not being able to nest aggregators, sql server

I'm grouping the tuples in a relation on InstructorNo and CourseNo, where a teacher is in a tuple with a course if they can teach it. I want to select instructors that can teach the same number of courses as the instructor in the list that can teach the most courses.
For example, if Mr.Smith can teach the most courses out of all the teachers in the relation I want to select Mr.Smith and anybody else that can teach the same number of courses he can.
What I'd really like to do is something like this:
select InstructorNo, COUNT(InstCourses.CourseNo) as NoTeachableCourses
from
...
group by InstructorNo
having COUNT(InstCourses.CourseNo) = MAX(COUNT(InstCourses.CourseNo))
But that's illegal because of the nested aggregations MAX(COUNT.... How can I get this functionality without being able to nest aggregators? I'm not sure how many teachers I'll need to select in a given query, so I'm not sure if TOP or TOP WITH TIES will work.
Use TOP or TOP WITH TIES:
select top(1) with ties InstructorNo, COUNT(InstCourses.CourseNo) as NoTeachableCourses
from
...
group by InstructorNo
order by NoTeachableCourses desc;

Selecting a grouping that matches a certain criteria, SQL

I have two relations, one is a list of the areas an instructor is able to teach (AreasOfInstructor(InstructorNo,AreaName)) and the other is the result of a subquery that returns a list of AreaNames. I want to group the AreaOfInstructor relation by InstructorNo, and then return each instructor (as represented by InstructorNo) that is able to teach all the areas returned by the subquery.
My attempt:
SELECT InstructorNo
FROM AreasofInstructor
GROUP BY InstructorNo
/**WHERE THE GROUP CONTAINS* (the list of AreaNames returned by the subquery)*/
I'm not sure what the actual SQL commands are that will implement the stuff between the stars on the last line. Thanks for the help!
Edit: Just to be clear, what I'm looking for is the set of instructors that are able to teach in the areas that are returned by the subquery.
To do this, you can join both relations, group by InstructorNo, and then validate that the distinct count of AreaNames per InstructorNo matches the distinct count of AreaNames in the AreaNames relation.
with AreaNames as (subquery)
select i.InstructorNo, count(distinct i.AreaName)
from AreasofInstructor i
join AreaNames n
on n.AreaName = i.AreaName
group by i.InstructorNo
having count(distinct i.AreaName) = (select count(distinct AreaName) from AreaNames)
It's better to use Common Table Expression are more readable than a sub-query.
Check if this is what you are looking for?
WITH Areas (AreaName)
AS
(
*sub-query goes here*
)
SELECT DISTINCT
InstructorNo
FROM
AreasOfInstructor AOI
INNER JOIN
Areas A ON AOI.AreaName = A.AreaName

I'm not sure what is the purpose of "group by" here

I'm struggling to understand what this query is doing:
SELECT branch_name, count(distinct customer_name)
FROM depositor, account
WHERE depositor.account_number = account.account_number
GROUP BY branch_name
What's the need of GROUP BY?
You must use GROUP BY in order to use an aggregate function like COUNT in this manner (using an aggregate function to aggregate data corresponding to one or more values within the table).
The query essentially selects distinct branch_names using that column as the grouping column, then within the group it counts the distinct customer_names.
You couldn't use COUNT to get the number of distinct customer_names per branch_name without the GROUP BY clause (at least not with a simple query specification - you can use other means, joins, subqueries etc...).
It's giving you the total distinct customers for each branch; GROUP BY is used for grouping COUNT function.
It could be written also as:
SELECT branch_name, count(distinct customer_name)
FROM depositor INNER JOIN account
ON depositor.account_number = account.account_number
GROUP BY branch_name
Let's take a step away from SQL for a moment at look at the relational trainging language Tutorial D.
Because the two relations (tables) are joined on the common attribute (column) name account_number, we can use a natural join:
depositor JOIN account
(Because the result is a relation, which by definition has only distinct tuples (rows), we don't need a DISTINCT keyword.)
Now we just need to aggregate using SUMMARIZE..BY:
SUMMARIZE (depositor JOIN account)
BY { branch_name }
ADD ( COUNT ( customer_name ) AS customer_tally )
Back in SQLland, the GROUP BY branch_name is doing the same as SUMMARIZE..BY { branch_name }. Because SQL has a very rigid structure, the branch_name column must be repeated in the SELECT clause.
If you want to COUNT something (see SELECT-Part of the statement), you have to use GROUP BY in order to tell the query what to aggregate. The GROUP BY statement is used in conjunction with the aggregate functions to group the result-set by one or more columns.
Neglecting it will lead to SQL errors in most RDBMS, or senseless results in others.
Useful link:
http://www.w3schools.com/sql/sql_groupby.asp