Postgres aggregate problem - sql

I'm not sure why this won't work:
SELECT u.id, u.tag, u.unit_type, Count(p.id) AS num_points
FROM ot2.unit u
INNER JOIN ot2.point p on p.unit_id = u.id
GROUP BY u.id
HAVING Count(p.id) > 800;
ERROR: column "u.tag" must appear in the GROUP BY clause or be used in an aggregate function
SQL state: 42803
I have already provided a column for group by.

Just what the error says. u.tag is not in the group by and you aren't telling how to aggregate the different u.tag values to a single one.
More concrete you have 2 options:
Add u.tag in the group by clause (and u.unit_type as well)
use an aggregate function on those 2 fields (min, max, sum, avg, ....)

Related

Postgres SQL: column must appear in the GROUP BY clause or be used in an aggregate function

(Postgres)
I'm not clear on the following: I'm selecting various fields from STUDY_T which may be sub-selects with aggregate functions. One independent field I'm retrieving is a LOOKUP_T join, lookupStudyType.description, which is not related to any aggregate functions. But I'm getting the error
ERROR: column "lookupstudytype.description" must appear in the GROUP BY clause or be used in an aggregate function
LINE 3: lookupStudyType.description AS studyTypeDescription,...
Why do I need to also group not just by s.id but also lookupStudyType.description (while the other s. groupings are not required)?
SELECT
s.id AS id,
lookupStudyType.description AS studyTypeDescription,
s.name AS name,
s.abbreviation AS abbreviation,
s.start_date AS startDate,
s.end_date AS endDate,
(SELECT COUNT(r.id)
FILTER
(WHERE r.status_id IN (76, 77) )) AS recallCount,
(SELECT COUNT(DISTINCT sp.id)) AS participantCount,
(SELECT MAX(r.created_date)
FILTER
(WHERE r.status_id IN (76,77) )) AS lastRecall,
s.login_access_required AS loginAccessRequired,
s.description AS description,
s.custom_participant_exit_message AS customParticipantExitMessage
FROM study_t s
INNER JOIN lookup_t lookupStudyType
ON s.study_type_id = lookupStudyType.id
INNER JOIN study_staff_t ss
ON s.id = ss.study_id
INNER JOIN users_t u
ON ss.researcher_id = u.id
LEFT JOIN study_participants_t sp
ON s.id = sp.study_id
LEFT JOIN recalls_t r
ON r.user_id = sp.user_id
WHERE u.user_name = 'test#test.com'
GROUP BY
s.id
ORDER BY s.abbreviation ASC
As a general rule, any column not listed in the GROUP BY clause should show up aggregated in the SELECT list.
For example s.name should show up as max(s.name) or min(s.name) since it's not present n the GROUP BY list. However, PostgreSQL implements functional dependency (a SQL Standard feature) for the GROUP BY clause, and detects that s.name is dependent in the s.id column (that is probably a PK); in short, there's a single possible value s.name for each s.id. Therefore, there's no need in PostgreSQL to aggregate this column (you can, but it's not needed).
On the flip side, for lookupStudyType.description PostgreSQL cannot determine if it's functionally dependent on s.id or not. You'll need to aggregate it as max(lookupStudyType.description) or min(lookupStudyType.description), or any other aggregation expression.
As a side note, I have rarely seen functional dependency implemented in other databases. Isn't PostgreSQL awesome? (I'm not affiliated with PostgreSQL in any way).

How to fix "Column 'ColumnName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."

Needing to fix the mentioned code error for my SQL query
Error: "Column 'ColumnName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."
I am under the impression that an aggregate function needs to be implemented, however I do not understand how.
My query:
SELECT
TransactionID,
InvoiceSum.TransNum,
PosTransaction.OrderID,
PosTransaction.PatientID,
Patient.ID,
Patient.MedicalRecordNum,
PosTransaction.OfficeNum AS Pos_OfficeNum,
Patient.ExamOffice,
TransactionDate,
Patient.FirstName,
Patient.LastName,
Patient.BirthDate,
Patient.Sex,
Item.ItemNum,
Item.ItemName
FROM PosTransaction Inner Join Patient ON PosTransaction.PatientID =
Patient.ID
Inner Join InvoiceSum ON PosTransaction.TransactionID =
InvoiceSum.TransNum
Inner Join InvoiceDet ON InvoiceSum.InvoiceID = InvoiceDet.InvoiceID
Inner Join Item ON InvoiceDet.ItemID = Item.ID
GROUP BY Patient.ID
ORDER BY TransactionDate
I am expecting to see duplicate customer names to be removed from the output once properly I understand how to use GROUP BY.
If you only group by patient.ID, what will happen to other columns?
(The server does not know what it should do, so it raises an error)
The server does not know what you want to do with the other columns.
(So You need the aggregate function(s) to tell the SQL server)
Simple example:
ID|salary
01|1000
01|2000
01|3000
If I only group by id here:
select id, salary
from sample
group by id
How do you want to calculate salary? Sum, max, min?
So you need the aggregate function:
select id, sum(salary)
from sample
group by id
Comment below if you have any questions.

SQL query error about movie.title is invalid

SELECT TOP(100) M.title, count(WH.movie_id)
FROM Movie AS M
inner join WatchHistory AS WH ON M.movie_id = WH.movie_id
GROUP BY WH.movie_id, M.title, count(WH.movie_id)
ORDER BY count(WH.movie_id) ASC;
BlockquoteColumn 'Movie.title' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
My assignment is to do the following query:
Show 100 films that have gone so far
were looked at. This also means 0 times [film title, number of times viewed].
Make a View for this information requirement.
It gives the error above
There are plenty of issues:
count(WH.movie_id) removed from a GROUP BY
Added alias [CountViews]
Alias used in ORDER BY instead of aggregate
Fixed SQL:
SELECT TOP(100) M.title, count(WH.movie_id) as [CountViews]
FROM Movie AS M
inner join WatchHistory AS WH ON M.movie_id = WH.movie_id
GROUP BY M.title
ORDER BY [CountViews] ASC;
You should only group by M.title. If you intend to group rows, decide which columns will be grouped. Remember that only columns in the GROUP BY clause, in addition to aggregate functions such as COUNT, may ultimately be included in the SELECT clause. Grouped aggregate functions operate on sets of rows defined in a GROUP BY clause and return a summarized result. Examples include SUM, MIN, MAX COUNT, and AVG. In the absence of a GROUP BY clause, all rows are considered one set; aggregation is performed on all of them.

GROUP BY not working in left join query

I m trying to use group by clause in left join sql query and it is not working.
Please help me out, thanks in advance.
SELECT Cust_Mst_Det.Cust_Hd_Code,
Cust_Mst_Det.First_Name,
SL_HEAD20152016.vouch_date AS invoice_2,
SL_HEAD20142015.vouch_date AS invoice_1,
Cust_Mst_Hd.EMail
FROM Cust_Mst_Det
LEFT JOIN SL_HEAD20142015 ON Cust_Mst_Det.Cust_Hd_Code=SL_HEAD20142015.Member_Code
LEFT JOIN SL_HEAD20152016 ON Cust_Mst_Det.Cust_Hd_Code=SL_HEAD20152016.Member_Code
LEFT JOIN Cust_Mst_Hd ON Cust_Mst_Det.Cust_Hd_Code=Cust_Mst_Hd.Cust_Hd_Code
WHERE cust_mst_det.first_name!='NIL'
GROUP BY Cust_Mst_Det.Cust_Hd_Code
ORDER BY SL_HEAD20152016.vouch_date DESC,
SL_HEAD20142015.vouch_date
I'm not sure which DBMS you are using, but on an Oracle your query will not work at all.
First issue: The GROUP BY statement is used in conjunction with the aggregate functions to group the result-set by one or more columns. You do not have any aggregating function in your SELECT statement (count, max, etc.)
Second issue: you must specify all columns from SELECT statement in your GROUP BY statement (excluding columns that represents results of aggregation).
As I said I don't know which DB is used by you, but those two points should be applicable for the most of SQL standards.
It appears that it is impossible to use an ORDER BY on a GROUP BY summarisation. My fundamental logic is flawed. I will need to run the following subquery.
ex :
SELECT p.*, pp.price
FROM products p
LEFT JOIN ( SELECT price FROM product_price ORDER BY date_updated DESC ) pp
ON p.product_id = pp.product_id GROUP BY p.product_id;
This will take a performance hit but as it is the same subquery for each row it shouldn't be too bad.

how to use count with where clause in join query

SELECT
DEPTMST.DEPTID,
DEPTMST.DEPTNAME,
DEPTMST.CREATEDT,
COUNT(USRMST.UID)
FROM DEPTMASTER DEPTMST
INNER JOIN USERMASTER USRMST ON USRMST.DEPTID=DEPTMST.DEPTID
WHERE DEPTMST.CUSTID=1000 AND DEPTMST.STATUS='ACT
I have tried several combination but I keep getting error
Column 'DEPTMASTER.DeptID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
I also add group by but it's not working
WHen using count like that you need to group on the selected columns,
ie.
SELECT
DEPTMST.DEPTID,
DEPTMST.DEPTNAME,
DEPTMST.CREATEDT,
COUNT(USRMST.UID)
FROM DEPTMASTER DEPTMST
INNER JOIN USERMASTER USRMST ON USRMST.DEPTID=DEPTMST.DEPTID
WHERE DEPTMST.CUSTID=1000 AND DEPTMST.STATUS='ACT'
GROUP BY DEPTMST.DEPTID,
DEPTMST.DEPTNAME,
DEPTMST.CREATEDT
you miss group by
SELECT DEPTMST.DEPTID,
DEPTMST.DEPTNAME,
DEPTMST.CREATEDT,
COUNT(USRMST.UID)
FROM DEPTMASTER DEPTMST
INNER JOIN USERMASTER USRMST ON USRMST.DEPTID=DEPTMST.DEPTID
WHERE DEPTMST.CUSTID=1000 AND DEPTMST.STATUS='ACT
group by DEPTMST.DEPTID,
DEPTMST.DEPTNAME,
DEPTMST.CREATEDT
All aggregate functions like averaging, counting,sum needs to be used along with a group by function. If you dont use a group by clause, you are performing the function on all the rows of the table.
Eg.
Select count(*) from table;
This returns the count of all the rows in the table.
Select count(*) from table group by name
This will first group the table data based on name and then return the count of each of these groups.
So in your case, if you want the countof USRMST.UID, group it by all the other columns in the select list.