Not a Group by expression error [joining tables] - sql

Group by not working when I tried to get maximum of the value column grouped with different subject names & staff names.
The select query inside first brace works fine and I'm getting the desired output from that. But, I'm not able to get maximum value for each staff, subject from that.
select staff_name, subject_name, max(value) from
(select Staff.staff_name, Subject.subject_name, Mark.value as value
from ((staff inner join subject on Staff.staff_id=Subject.staff_id)
inner join Mark ON Mark.subject_id=Subject.subject_id)
group by subject_name);
Error is:
ORA-00979: not a GROUP BY expression

Seems you have wrong sequence for nested ()
and you have missed a not aggregated column in group by
select t.staff_name, t.subject_name, max(t.value)
from (
select Staff.staff_name, Subject.subject_name, Mark.value as value
from staff
inner join subject on Staff.staff_id=Subject.staff_id
inner join Mark ON Mark.subject_id=Subject.subject_id
) t
group by t.staff_name, t.subject_name;

Looks like you just need this:
select st.staff_name, su.subject_name, max(mk.value)
from staff st
join subject su
on su.staff_id = st.staff_id
join mark mk
on mk.subject_id = su.subject_id
group by st.staff_name, su.subject_name

Related

Group By and Inner Join Together To Get Unique Values By Maximum Date

I have a table here in which I want to write a SELECT query in SQL Server that allows me to get the following:
For each unique combination of SalesPerson x Country, get only the rows with the latest Upload_DateTime
However, I am trying to do a group-by and inner join, but to no avail. My code is something like this:
SELECT t1.[SalesPerson], t1.[Country], MAX(t1.[Upload_DateTime]) as [Upload_DateTime]
FROM [dbo].[CommentTable] AS t1
GROUP BY t1.[SalesPerson], t1.[Country]
INNER JOIN SELECT * FROM [dbo].[CommentTable] as t2 ON t1.[SalesPerson] = t2.[SalesPerson], t1.[Country] = t2.[Country]
It seems like the GROUP BY needs to be done outside of the INNER JOIN? How does that work? I get an error when I run the query and it seems my SQL is not right.
Basically, this subquery will fetch the person, the country and the latest date:
SELECT
SalesPerson, Country, MAX(uplodaed_datetime)
FROM CommentTable
GROUP BY SalesPerson, Country;
This can be used on a lot of ways (for example with JOIN or with an IN clause).
The main query will add the remaing columns to the result.
Since you tried a JOIN, here the JOIN option:
SELECT
c.id, c.SalesPerson, c.Country,
c.Comment, c.uplodaed_datetime
FROM
CommentTable AS c
INNER JOIN
(SELECT
SalesPerson, Country,
MAX(uplodaed_datetime) AS uplodaed_datetime
FROM CommentTable
GROUP BY SalesPerson, Country) AS sub
ON c.SalesPerson = sub.SalesPerson
AND c.Country = sub.Country
AND c.uplodaed_datetime = sub.uplodaed_datetime
ORDER BY c.id;
Try out: db<>fiddle

SQL Group By Throwing Up Error (SQL Server)

I have SQL code that throws up an error saying
Error: SQLCODE=-119, SQLSTATE=42803, SQLERRMC=WONUM
The code works fine until I add the group by:
select *
from workorder
left join labtrans on labtrans.refwo=workorder.wonum and labtrans.siteid=workorder.siteid
left join matusetrans on workorder.wonum=matusetrans.refwo and workorder.siteid=matusetrans.tositeid and linetype not in (select value from synonymdomain where domainid='LINETYPE' and maxvalue='TOOL')
left join locations on locations.location = workorder.location and locations.siteid=workorder.siteid
left join person on personid in (select personid from labor where laborcode = labtrans.laborcode)
left join po on workorder.wonum=po.hflwonum and workorder.siteid=po.siteid and workorder.orgid=po.orgid
left join companies on companies.company = po.vendor and companies.orgid=po.orgid
left join pluspcustomer on pluspcustomer.customer=workorder.pluspcustomer
where workorder.wonum='10192'
group by personid
;
if you only GROUP BY personid, you cannot select everything except personid, OR the fields used by aggregate functions such as SUM,MAX, etc
UPDATE
If you just want to see the duplicate personid, you could use:
select personid
from table
group by personid
But be careful here: If you write query like this, the only field that to determine the duplicate records is persionid, if you need to uniquely identify each persionid from different CompanyId, you need to group by persionid, CompanyId, otherwise, same personId from different company will be considered as the duplicate records.
But if you want to delete those duplicate records, you should use ROW_NUMBER()OVER (Partition by persionid Order by your_criteria) to delete the duplicate records. Try to do some searches to see how does that work, usually I prefer to use that function along with the CTE table expression.
if you just need to remove duplicates, use DISTINCT with your query like this:
your query:
SELECT * FROM .....
modify it:
SELECT DISTINCT * FROM .....
Hope it helps.

How to get the value of max() group when in subquery?

So i woud like to find the department name or department id(dpmid) for the group that has the max average of age among the other group and this is my query:
select
MAX(avg_age) as 'Max average age' FROM (
SELECT
AVG(userage) AS avg_age FROM user_data GROUP BY
(select dpmid from department_branch where
(select dpmbid from user_department_branch where
user_data.userid = user_department_branch.userid)=department_branch.dpmbid)
) AS query1
this code show only the max value of average age and when i try to show the name of the group it will show the wrong group name.
So, How to show the name of max group that has subquery from another table???
You may try this..
select MAX(avg_age) as max_avg, SUBSTRING_INDEX(MAX(avg_age_dep),'##',-1) as max_age_dep from
(
SELECT
AVG(userage) as avg_age, CONCAT( AVG(userage), CONCAT('##' ,department_name)) as avg_age_dep
FROM user_data
inner join user_department_branch
on user_data.userid = user_department_branch.userid
inner join department_branch
on department_branch.dpmbid = user_department_branch.dpmbid
inner join department
on department.dpmid = department_branch.dpmid
group by department_branch.dpmid
) tab_avg_age_by_dep
;
I've done some change on ipothesys that the department name is placed in a "department" anagraphical table.. so, as it needed put in join a table in plus, then I changed your query, eventually if the department name is placed (but I don't thing so) in the branch_department table you can add the field and its treatment to your query
update
In adjunct to as said, if you wanto to avoid identical average cases you can furtherly make univocal the averages by appending a rownum id in this way:
select MAX(avg_age) as max_avg, SUBSTRING_INDEX(MAX(avg_age_dep),'##',-1) as max_age_dep from
(
SELECT
AVG(userage) as avg_age, CONCAT( AVG(userage), CONCAT('##', CONCAT( #rownum:=#rownum+1, CONCAT('##' ,department_name)))) as avg_age_dep
FROM user_data
inner join user_department_branch
on user_data.userid = user_department_branch.userid
inner join department_branch
on department_branch.dpmbid = user_department_branch.dpmbid
inner join department
on department.dpmid = department_branch.dpmid
,(SELECT #rownum:=0) r
group by department_branch.dpmid
) tab_avg_age_by_dep
;
I took a shot at what I think you are looking for. The following will give you the department branch with the highest average age. I assumed the department_branch table had a department_name field. You may need an additional join to get the department.
SELECT db.department_name, udb.dpmid, AVG(userage) as `Average age`
FROM user_data as ud
JOIN user_department_branch as udb
ON udb.userid = ud.userid
JOIN department_branch as db
ON db.dpmbid = udb.dpmbid
GROUP BY udb.dpmid
ORDER BY `Average age` DESC
LIMIT 1

How to use an inner join with group by or count function

I'm use this SQL query to fetch data from a access database
SELECT Absence.date_, stages.name, course.course_name, student.name AS st_name
FROM (((Absence INNER JOIN course ON Absence.course_id = course.ID)
INNER JOIN stages ON course.id_stage = stages.ID)
INNER JOIN student ON Absence.student_id = student.ID AND stages.ID = student.stage_id`
when i wont to group the field or get count of field it show to me this error message
Tried to execute a query that does not include the specified
expression 'Absence.date_' as part of an aggregate function
how can i get number of row ,distinct it by st_name , and group by stage name or course name
For getting the count you should use
SELECT Absence.date_, stages.name, course.course_name, student.name AS st_name, count(*)
FROM (((Absence INNER JOIN course ON Absence.course_id = course.ID)
INNER JOIN stages ON course.id_stage = stages.ID)
INNER JOIN student ON Absence.student_id = student.ID AND stages.ID = student.stage_id
GROUP BY Absence.date_, stages.name, course.course_name, student.name
What table contains the field "Absence.date_" ?
And you do not need to specify "Inner" (or Natural for that matter).
When using aggregate functions (Count(), Sum(), ect) your group by must contain the same list of fields as your select statement. And that error states that either Absence.date_ does not exist as a field in any of the tables in the from clause. But, you have no Group By statement in your query.

How to use WITH clause and select clause

click here to view screenshot of table
Question: write a query to display the customer number, firstname, lastname for those client where total loan amount taken is maximum and at least taken from 2 bank branch.
I have tried the following query but I'm getting this error
Msg 8120, Level 16, State 1, Line 7
Column 'customer.fname' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Code:
with l as
(
select custid, sum(loan_amount) as tot
from loan
group by custid
having count(bid) >= 2
)
select
concat(c.fname, c.ltname) as name,
max(l.tot)
from
customer as c, l
where
l.custid = c.custid
You need to have a GROUP BY to select both aggregated and non-aggregated data, so you need to decide how you want the data grouped. You could do either
SELECT CONCAT(c.fname,c.ltname) as name, MAX(l.tot)
FROM customer AS c
INNER JOIN l ON l.custid=c.custid
GROUP BY c.fname,c.ltname
or
SELECT CONCAT(c.fname,c.ltname) as name, MAX(l.tot)
FROM customer AS c
INNER JOIN l ON l.custid=c.custid
GROUP BY concat(c.fname,c.ltname)
Please note the following:
I converted the "old" join syntax to the more acceptable INNER JOIN syntax
You probably want a space between the first and late name if you're displaying the results.