How can I use the GROUP BY SQL clause with no aggregate function? - sql

When I try to use the following SELECT statement:
SELECT [lots of columns]
FROM Client, Customer, Document, Group
WHERE [some conditions]
GROUP BY Group.id
SQL Server complains that the columns I selected are not part of the GROUP BY statement nor an aggregate function. Am I using GROUP BY wrong? What should I be using instead?

To return all single occurences of a group by field, together with associated field values, write a query like:
select group_field,
max(other_field1),
max(other_field2),
...
from mytable1
join mytable2 on ...
group by group_field
having count(*) = 1;

Yes, you are using GROUP BY incorrectly. The point of using GROUP BY is to use aggregate functions. If you have no aggregrate functions you probably want SELECT DISTINCT instead.
SELECT DISTINCT
col1,
col2,
-- etc
coln
FROM Client
JOIN Customer ON ...
JOIN Document ON ...
JOIN [Group] ON ...
WHERE ...

My first guess would be that the problem is that you have table called Group, which I believe is a reserved word in SQL. Try wrapping the Group name with ' '

You want to group by all columns you are selecting that is not in an aggregate funcion.
SELECT ProductName, ProductCategory, SUM(ProductAmount)
FROM Products
GROUP BY ProductName, ProductCategory
This will give you a disticnt result of Product names and categories with the sum total of product amount in all aggregate child records for that group.

Related

Join table to CTE and group by

I have a CTE that contains lots of joins and condition (mydashboard) and
I am trying to join the CTE to another table and show an additional column with the count of the second table.
What am I doing wrong?
select *, count(t_KPIRespConn.RespID)
from mydashboard
join t_kpirespconn on mydashboard.kpicodeid = t_kpirespconn.kpicodeid
group by mydashboard.KPIcodeID
Column 'mydashboard.code' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Thanks
You will need to group by all non aggregated fields, meaning all fields in the SELECT list that are not used in an aggregate function, in your case, all field besides t_KPIRespConn.RespID.
Solution 1:
select field1, field2, field3,... fieldN, count(t_KPIRespConn.RespID)
from mydashboard
join t_kpirespconn on mydashboard.kpicodeid = t_kpirespconn.kpicodeid
group by mydashboard.KPIcodeID, field1, field2, field3, ...fieldN
Using a window function basically achieves the same thing but it is less verbose. You are not required to GROUP BY as the window function aggregates the values on the partition specified. For COUNT() you can specify OVER(), which means the entire results set in the group.
Solution 2:
select *,
count(*) OVER() //<-- Use this if you want the count of all records
from mydashboard
join t_kpirespconn on mydashboard.kpicodeid = t_kpirespconn.kpicodeid
Use the same window function but narrow the partition to any grouping you would like. In this case, the counts would pertain to all records with matching t_KPIRespConn.RespID values.
Solution 3:
select *, count(*) OVER(PARTITION BY t_KPIRespConn.RespID) //<-- Use this if you want the count of all records with the same t_KPIRespConn.RespID
from mydashboard
join t_kpirespconn on mydashboard.kpicodeid = t_kpirespconn.kpicodeid
select * .. group by mydashboard.KPIcodeID is your true issue. When you run aggregate functions, you must explicitly supply any columns that are non-aggregated in the select list in the group by. This will work
select mydashboard.KPIcodeID, count(t_KPIRespConn.RespID)
from mydashboard
join t_kpirespconn on mydashboard.kpicodeid = t_kpirespconn.kpicodeid
group by mydashboard.KPIcodeID

Why does adding GROUP BY cause a seemingly unrelated error?

The following code works fine:
SELECT name, (SELECT count(item_id) FROM bids WHERE item_id = items.id)
FROM items;
However, when I add
SELECT name, (SELECT count(item_id) FROM bids WHERE item_id = items.id)
FROM items
GROUP BY name;
I get ERROR: subquery uses ungrouped column "items.id" from outer query
Can anyone tell me why this is happening? Thanks!
If you GROUP BY name then any other columns you select from items must have an aggregate function applied. That's what GROUP BY means.
In your case, you are using another column from items -- id -- in a correlated scalar subquery. That's not an aggregate function, and id is not in the GROUP BY clause, so you get an error.
You could instead GROUP BY name, id. That should give you the same results as the first query, and is probably pointless.
If you actually have multiple rows in items with the same value for name, and you want to group the results of the scalar subquery for those values, you need to specify how to group them. Perhaps you want the total of the subquery results for each value of name. If so, I think you could do:
SELECT name, SUM(SELECT count(item_id) FROM bids WHERE item_id = items.id))
FROM items
GROUP BY name;
(I'm not positive about the specific syntax as I don't have a Postgres instance to test against.)
A clearer way to express it might be:
SELECT name, SUM(bid_count)
FROM (
SELECT name, (SELECT count(item_id) FROM bids WHERE item_id = items.id) AS bid_count
FROM items
)
GROUP BY name
Join the tables then perform the GROUP BY:
select i.name, count(b.item_id)
from items i
inner join bids b
on b.item_id = i.id
group by i.name
db<>fiddle here

SAS SQL SELECT DISTINCT WITH GROUP BY

What if a SQL code as below?
Proc SQL;
SELECT DISTINCT ID,SUM(AMOUNT) AS M,SUM(NO) AS CNT
FROM CUSTOMER_LIST
GROUP BY ID
ORDER BY CNT DESC;
QUIT;
Use DISTINCT with GROUP BY. Any possible error will occur when using this combination Or DISTINCT just a redundant word?
Thanks~
Use DISTINCT with GROUP BY. Any possible error will occur when using this combination? Or DISTINCT just a redundant word?
This won't error, but that's just unnecessary redondancy. GROUP BY ID guarantees that each ID will appear only on one row in the resulset. There is no benefit for adding DISTINCT here - and it makes the intent of the query harder to understand.
On the other hand, there are situations where you would use DISTINCT without GROUP BY: typically when you want to deduplicate a set of columns, but do not need to use aggregate functions (SUM(), COUNT()...).
SELECT ID,SUM(AMOUNT) AS M,SUM(NO) AS CNT
FROM CUSTOMER_LIST
GROUP BY ID
ORDER BY CNT DESC;
We already group by id so no need distinct id

SQL Server: How can I use the COUNT clause without GROUPing?

I'm looking get two things from a query, given a set of contraints:
The first match
The total number of matches
I can get the first match by:
SELECT TOP 1
ID,
ReportYear,
Name,
SignDate,
...
FROM Table
WHERE
...
ORDER BY ... //I can put in here which one I want to take
And then I can get the match count if I use
SELECT
MIN(ID),
MIN(ReportYear),
MIN(Name),
MIN(SignDate),
... ,
COUNT(*) as MatchCount
FROM Table
WHERE
...
GROUP BY
??? // I don't really want any grouping
I really want to avoid both grouping and using an aggregate function on all my results. This question SQL Server Select COUNT without using aggregate function or group by suggests the answer would be
SELECT TOP 1
ID,
ReportYear,
Name,
SignDate,
... ,
##ROWCOUNT as MatchCount
FROM Table
This works without the TOP 1, but when it's in there, ##ROWCOUNT = number of rows returned, which is 1. How can I get essentially the output of COUNT(*) (whatever's left after the where clause) without any grouping or need to aggregate all the columns?
What I don't want to do is repeat each of these twice, once for the first row and then again for the ##ROWCOUNT. I'm not finding a way I can properly use GROUP BY, because I strictly want the number of items that match my criteria, and I want columns that if I GROUPed them would throw this number off - unless I'm misunderstanding GROUP BY.
Assuming you are using a newish version of SQL Server (2008+ from memory) then you can use analytic functions.
Simplifying things somewhat, they are a way of way of doing an aggregate over a set of data instead of a group - an extension on basic aggregates.
Instead of this:
SELECT
... ,
COUNT(*) as MatchCount
FROM Table
WHERE
...
You do this:
SELECT
... ,
COUNT(*) as MatchCount OVER (PARTITION BY <group fields> ORDER BY <order fields> )
FROM Table
WHERE
...
GROUP BY
Without actually running some code, I can't recall exactly which aggregates that you can't use in this fashion. Count is fine though.
Well, you can use OVER clause, which is an window function.
SELECT TOP (1)
OrderID, CustID, EmpID,
COUNT(*) OVER() AS MatchCount
FROM Sales.Orders
WHERE OrderID % 2 = 1
ORDER BY OrderID DESC
Try next query:
select top 1
*, count(*) over () rowsCount
from
(
select
*, dense_rank() over (order by ValueForOrder) n
from
myTable
) t
where
n = 1

SQL To get Distinct Name and Number from table

Looking for sql to get distinct names and count of those names from a sql table:
Structure:
id
name
other details
Do I use distinct to get each group and then count through those to get:
name1 count(name1)
name2 count(name2)
etc
Thanks
Rob.
When you want a COUNT() or a SUM(), you're using an AGGREGATE FUNCTION based on a GROUP BY clause.
As GROUP BY brings together all records with the same values specified in the GROUP BY columns, you're already getting the same effect as DISTINCT.
Except that DISTINCT doesn't allow aggregates, and GROUP BY does.
SELECT
name,
COUNT(*) AS count_of_name
FROM
yourTable
GROUP BY
name
Try :
SELECT *, COUNT(*) FROM my_table GROUP BY name
Something like this?
select name,COUNT(name) FROM Persons GROUP BY name
In the end I used:
SELECT DISTINCT `school`,COUNT(`school`) AS cat_num FROM table GROUP BY school order by cat_num DESC