SQL: Finding the Minimum aggregate using only count - sql

I'm using DB2 for a project and looking to find which Group has the fewest members without using the min feature. My idea is to find all the groups and then subtract out any group which has more members from some other group thus leaving me with the group with that has no more members than any other group, i.e. the min.
So far I have
SELECT DISTINCT P.group as Group, count(P.id) as Count
FROM People P
EXCEPT
SELECT P.group, count(P.id)
FROM People P, People O
WHERE count(P.cid) > count(O.cid);
With a schema for People like
create table People (
group varchar(25) not null,
id smallint not null,
);
I am getting the following error:
SQL0119N An expression starting with "CLUB" specified in a SELECT clause,
HAVING clause, or ORDER BY clause is not specified in the GROUP BY clause or
it is in a SELECT clause, HAVING clause, or ORDER BY clause with a column
function and no GROUP BY clause is specified. SQLSTATE=42803
If you could help point out what I am doing wrong or the correct format for such a query it would be greatly appreciated!

find which Group has the fewest members
You can aggregate by group, order by member count, and fetch the top row only:
select p.group as grp, count(*) as cnt
from people p
group by p.group
order by count(*)
fetch first 1 rows only

You should try to use min(). Very straight forward. From your Error message, it seems like your HAVING clause is wrong so it would look into that.

Related

Find Min in rows in SQL table

I am trying to find all the clubs in my database that appear the least number of times in the database and display that club name and how many times it appeared. Below is my solution for what I tried
select club, MIN(num)
from
(select count(club) as num
from member
order by club)
But this code throws an error:
SQL0119N An expression starting with "CLUB" specified in a SELECT clause, HAVING clause, or ORDER BY clause is not specified in the GROUP BY clause or it is in a SELECT clause, HAVING clause, or ORDER BY clause with a column function and no GROUP BY clause is specified.
I am new to SQL - can someone please tell me what is wrong and how I can fix this?
You could use the fetch first n rows only syntax:
SELECT club, COUNT(*)
FROM members
GROUP BY club
ORDER BY 2 ASC
FETCH FIRST 1 ROWS ONLY
You're heading in roughly the right direction. You need to do a double-aggregate.
WITH Member_Count AS (SELECT club, COUNT(*) AS counted
FROM Members
GROUP BY club)
SELECT club, counted
FROM Member_Count
WHERE counted = (SELECT MIN(counted)
FROM Member_Count)

not a single-group group function (00937. 00000)

SELECT p.pdept.dno,
MAX(SUM(p.budget)) AS max
FROM Proj111 p
GROUP BY p.pdept.dno
Although I have included all the necessary attributes in select statements to group by clause it will generate above issue? How to solve it?
You can't nest aggregate functions like that. If you want to get the maximum sum from each group, then you can try this:
WITH cte AS (
SELECT p.pdept.dno AS dept,
SUM(p.budget) AS budget
FROM Proj111 p
GROUP BY p.pdept.dno
)
SELECT t.dept,
t.budget
FROM cte t
WHERE t.budget = (SELECT MAX(budget) FROM cte)
The common table expression which I have named cte finds the budgets for each department. The query then restricts this result to the department with the maximum budget by again querying the cte for the maximum budget.

SQLPLUS (Oracle) - Get MAX COUNT of GROUPBY

I need to identify which Month has the most entries. Ive used the TO_DATE function to format the date column to just the MONTH. Also, SELECT COUNT(*) in combination with the GROUP BY Clause I am able to return all records month and count attributes.
However, I need to be able to only return one row that is the MAX of the COUNT. IVE atempted to do so by adding a HAVING clause but returns an error. I suspect I need a subquery in here somewhere but am unsure as to how to go about it.
SELECT TO_CHAR(P.DATEREGISTERED,'MONTH') MONTH, COUNT(*) COUNT
FROM PET P
GROUP BY TO_CHAR(P.DATEREGISTERED,'MONTH')
HAVING COUNT = MAX(COUNT);
Another Attempt:
SELECT TO_CHAR(P.DATEREGISTERED,'MONTH') MONTH, COUNT(*) COUNT
FROM PET P
GROUP BY TO_CHAR(P.DATEREGISTERED,'MONTH')
HAVING COUNT(*) = (SELECT MAX(TO_CHAR(P.DATEREGISTERED,'MONTH')) FROM PET P);
In the query with alias, you are grouping by Month and getting a count of the number of records and you are checking whether that count is same as the maximum of the "date value" converted to month string. They are not even comparisons of the same type.
The query that you have provided in the answer correctly compares the count on both sides.
Another way to rewrite the query would be
select * from
(SELECT TO_CHAR(P.DATEREGISTERED,'MONTH') MONTH, COUNT(*) COUNT
FROM PET P
GROUP BY TO_CHAR(P.DATEREGISTERED,'MONTH') order by count(*) desc )
where rownum=1
Here we order the records in the subquery by descending order of the count and then getting the first row from that.
The bellow code works and returns the correct response. It is unclear to me as to why it works but the above attempts (w/ aliases) do not.
SELECT TO_CHAR(P.DATEREGISTERED,'MONTH') MONTH, COUNT(*) COUNT
FROM PET P
GROUP BY TO_CHAR(P.DATEREGISTERED,'MONTH')
HAVING COUNT(*) = (SELECT MAX(COUNT(*)) FROM PET P GROUP BY TO_CHAR(P.DATEREGISTERED,'MONTH'));

Combine two SQL queries, one involving GROUP BY?

I would like to combine these two SQL queries into one.
SELECT COUNT() as total_grants, SUM("CURRENT_AWARD") as total_spent FROM t;
SELECT YEAR, COUNT(), SUM('CURRENT_AWARD') FROM t GROUP BY YEAR AS by_year;
The first query shows the total number of grants, and the total spent. The second is the same, but by year.
Is this possible? I've already combined two queries into one in the first query, but I can't figure out how to use an AS clause properly in the second query.
Thanks for any help.
How about using CROSS JOIN
SELECT YEAR,
COUNT(*),
SUM('CURRENT_AWARD') ,
t2.total_grants,
t2.total_spent
FROM t
CROSS JOIN
(
SELECT COUNT(*) as total_grants,
SUM("CURRENT_AWARD") as total_spent
FROM t
) t2
GROUP BY YEAR;
Maybe something like this?
SELECT BY_YEAR, COUNT(), SUM('CURRENT_AWARD') FROM t GROUP BY rollup(by_year);
(I think rollup can be rdbms/version dependent...)
Try this.
SELECT YEAR, COUNT(*) as total_grants, SUM(CURRENT_AWARD) as total_spent
FROM t
GROUP BY YEAR;
COUNT(*) will count all rows in table t, including ones with NULL. If you want to ignore rows with NULL, count a specific column. For example, COUNT(CURRENT_AWARD).
You don't need the quotes around CURRENT_AWARD since this identifier contains only letters and underscores.

GROUP BY Function Issue

I have the below example:
SELECT name, age, location, SUM(pay)
FROM employee
GROUP BY location
This as expected will give me an error:
ORA-00979: not a GROUP BY expression
How can I get around this? I need to group by one maybe two columns but need to return all columns even if they're not used in the GROUP BY clause, I've looked at sub-queries to get around it but have had no luck so far.
You can use analytic functions:
SELECT name
, age
, location
, pay
, SUM(pay) over (partition by location order by location ) total
FROM employee
So, you can return all rows even if they are not used in the grouping.
So you want to know the total pay by location, and you want to know the names and ages of employees at each location? How about:
SELECT e.NAME,
e.AGE,
e.LOCATION,
t.TOTAL_LOCATION_PAY
FROM EMPLOYEE e
INNER JOIN (SELECT LOCATION,
SUM(PAY) AS TOTAL_LOCATION_PAY
FROM EMPLOYEE
GROUP BY LOCATION) t
ON (t.LOCATION = e.LOCATION)
Share and enjoy.
(Group b[http://docs.oracle.com/javadb/10.6.2.1/ref/rrefsqlj32654.html] Must have an aggregate function in every column that is not in the group by clause. When you are grouping, means that you want one row per group. Distinct values of the columns in the clause appear in the final result set.
This is because oracle can't know which of the values for the column that you don't have in the group by to retrieve. Consider this:
A X
B X
Select col1, col2 from myTable group by col2; -- incorrect
Select min(col1), col2 from myTable group by col2; -- correct
Why is the first incorrect? Because oracle can't know whether to retrieve A or B for the X value you have to specify it. i.e. MIN, MAX, etc.
There is an alternative to this named analytic functions that allow you to work under windows of your result set.
Now if you want total employee pay by location, and every employee you may want this.
SELECT name, age, location, SUM(pay) OVER(PARTITION BY location)
FROM employee
I believe this is better than #Bob Jarvis query as you only query the table once. Please correct me if I'm wrong. He also has employees and employee. Typo?