ORA-00979: not a GROUP BY expression in Oracle - oracle

I can not execute this code on Oracle, the error shows:
"ORA-00979: not a GROUP BY expression"
However, I was able to run it successfully on MySQL.
How does this happen?
SELECT CONCAT(i.lname, i.fname) AS inst_name,
CONCAT(s.lname, s.fname) AS stu_name,
t.avg_grade AS stu_avg_grade
FROM(
SELECT instructor_id, student_id, AVG(grade) as avg_grade, RANK() OVER(PARTITION BY instructor_id ORDER BY grade DESC) AS rk
FROM grade
GROUP BY 1,2) t
JOIN instructor i
ON t.instructor_id = i.instructor_id
JOIN student s
ON s.student_id = t.student_id
WHERE t.rk = 1
ORDER BY 3 DESC

You can't use ordinals like GROUP BY 1,2 in Oracle. In addition, the ORDER BY grade clause inside your RANK() function has a problem. Keep in mind that analytic functions evaluate after the GROUP BY aggregation, so grade is no longer available. Here is a version which should work without error:
SELECT CONCAT(i.lname, i.fname) AS inst_name,
CONCAT(s.lname, s.fname) AS stu_name,
t.avg_grade AS stu_avg_grade
FROM
(
SELECT instructor_id, student_id, AVG(grade) AS avg_grade,
RANK() OVER (PARTITION BY instructor_id ORDER BY AVG(grade) DESC) AS rk
FROM grade
GROUP BY instructor_id, student_id
) t
INNER JOIN instructor i
ON t.instructor_id = i.instructor_id
INNER JOIN student s
ON s.student_id = t.student_id
WHERE t.rk = 1
ORDER BY t.avg_grade DESC;

Related

Oracle Left join give duplicate

I am trying to get all the customers whether they have install service or not from TRANS_TABLE.
NOA- query to get only the MAX product and join again with TRANS_TABLE by email id to get the all the MAX customers details (wwhther they have install service by adding Y OR N, but this query return duplicate with REP Product as well
Below is my Oracel Query which give duplicated
with CTE as (SELECT NOA.*,
CASE
WHEN TRANS_TABLE.product_name LIKE '%Installation%' THEN 'Y'
ELSE 'N'
END AS Installaion ,
ROW_NUMBER() OVER (PARTITION BY TRANS_TABLE.email_address ORDER BY TRANS_TABLE.email_address) AS rn
FROM (SELECT DISTINCT email_address
FROM TRANS_TABLE
WHERE email_address IS NOT NULL
and pdct_name like '%MAX%'
) NOA
LEFT JOIN TRANS_TABLE
ON NOA.email_address = TRANS_TABLE.email_address
select * from cte where rn='1'
The following code will help:
CTE AS (
SELECT
NOA.*,
CASE
WHEN TRANS_TABLE.PDCT_NAME LIKE '%INSTALLATION%' THEN 'Y' -- case sensitive name is used
ELSE 'N'
END AS INSTALLAION,
ROW_NUMBER() OVER(
PARTITION BY TRANS_TABLE.EMAIL_ADDRESS
ORDER BY
TRANS_TABLE.EMAIL_ADDRESS
) AS RN
FROM
(
SELECT DISTINCT
PDCT_NAME,
EMAIL_ADDRESS
FROM
TRANS_TABLE
WHERE
EMAIL_ADDRESS IS NOT NULL
AND PDCT_NAME LIKE '%MAX%'
) NOA
LEFT JOIN TRANS_TABLE ON NOA.EMAIL_ADDRESS = TRANS_TABLE.EMAIL_ADDRESS
WHERE TRANS_TABLE.PDCT_NAME NOT LIKE '%REP%') -- added this WHERE condition
SELECT
PDCT_NAME, EMAIL_ADDRESS, INSTALLAION
FROM
CTE
WHERE
RN = '1'
db<>fiddle demo
Cheers!!

Write a query to find the name of the student(s) who has scored maximum mark in Software Engineering. Sort the result based on name

Write a query to find the name of the student(s) who has scored maximum mark in Software Engineering. Sort the result based on name.
This is what I tried.
select s.student_name
from student s,mark m,subject su
where s.student_id=m.student_id and su.subject_id=m.subject_id and max(m.value)in
(select value from mark where lower(su.subject_name)='software engineering')
order by s.student_name;
I am not getting the proper result.
Apart from the fact that you're using outdated implicit comma syntax for joins, you are also combining columns of the tables in the wrong way in the sub query.
subject_name is a column of subject which has nothing to do with the student's relation to marks. So, mark may be joined separately with subject while determining the student_ids with highest mark. We can then obtain the name of the student using those student_ids
So, In Oracle 12c and above, you could do
SELECT s.student_name
FROM student s
WHERE s.student_id IN ( SELECT m.student_id
FROM mark m JOIN subject su
ON su.subject_id = m.subject_id
WHERE lower(su.subject_name) = 'software engineering'
ORDER BY m.value DESC
FETCH FIRST 1 ROWS WITH TIES ) order by 1;
For previous versions, you may use dense_rank or rank
SELECT s.student_name
FROM student s
WHERE s.student_id IN ( SELECT student_id
FROM ( SELECT m.*,DENSE_RANK() OVER(
ORDER BY m.value DESC
) AS rnk
FROM mark m JOIN subject su
ON su.subject_id = m.subject_id
WHERE lower(su.subject_name) = 'software engineering'
) WHERE rnk = 1
) order by 1;
you need to add the max function in the subquery instead of the main query.
select s.student_name
from student s, mark m, subject su
where s.student_id = m.student_id
and su.subject_id = m.subject_id
and m.value in
(select max(value)
from mark
where lower(su.subject_name) = 'software engineering')
order by s.student_name;
You can try this code. It must work perfectly :
select s.student_name
from student s
join mark m
on s.student_id=m.student_id
join subject s1
on s1.subject_id=m.subject_id
where m.value=(select max(m1.value) from mark m1
join subject s2
on s2.subject_id=m1.subject_id
where lower(s2.subject_name)='software engineering'
group by s2.subject_id)
group by s.student_name
order by s.student_name;
select student_name
from student join mark using(student_id) join subject using(subject_id)
where subject_name = 'Software Engineering'
and value = (select max(value)
from mark join subject using (subject_id)
where subject_name = 'Software Engineering')
order by student_name;
This is very self-explanatory solution.
select student_name
from student s join mark m on s.student_id=m.student_id
join subject sub on m.subject_id=sub.subject_id
where lower(sub.subject_name)='software engineering' and
m.value = (select max(m1.value)
from mark m1 join subject sub1 on m1.subject_id=sub1.subject_id
where lower(sub1.subject_name)='software engineering')
order by student_name;
select student_name
from stundent
where student_id in(
select student_id
from mark
where value=(select max(value) from mark
where subject_id=(
select subject_id
from subject
where lower(subject_name)='software engineering'
)
)
)
)
order by student_name;
select student_name
from student
where student_id in
(select student_id
from subject join mark using(subject_id)
where value in
(select max(value)
from mark
group by student_id
having initcap(subject_name) = 'Software Engineering'))
order by student_name;

i am getting the error ORA-00979. Point out the error

SELECT department_name, cou FROM
(
SELECT department_name, count(student_id) AS cou
FROM department d NATURAL JOIN student s
GROUP BY department_name
)
GROUP BY department_name HAVING cou=max(cou);
First off - avoid natural join. Its dangerous. Google for the reasons.
The message you are getting is because you have a GROUP BY for the OUTER select but you have no aggregating function in the select clause.
It looks like you can probably just lose the outer select completely and put the HAVING clause on the inner select.
SELECT * FROM (
SELECT department_name, count(student_id) AS cou
FROM department d
JOIN student s USING (student_id)
GROUP BY department_name
ORDER BY count(student_id) DESC )
WHERE rownum = 1

How can we use partition in Oracle query

I have query in which i used partition of avoid the duplicate value for particular column , but still it is giving duplicate row below i am mention my query in which i used partition
SELECT iol.M_product_id as faultyProduct , iol.SERIALNO,iol.M_product_id as newproduct, ma.Description,
mp.M_Product_category_id ,mi.issotrx, co.C_BPartner_ID,
ROW_NUMBER() OVER(PARTITION BY ma.Description ORDER BY iol.M_product_id DESC) rn
FROM M_inoutline iol
inner join M_inout mi ON (iol.m_inout_id = mi.m_inout_id)
inner join C_Order co ON (co.c_order_id = mi.c_order_id )
inner Join M_AttributeSetInstance ma ON (ma.m_attributesetinstance_id =iol.m_attributesetinstance_id)
inner join M_Product mp ON (mp.m_product_id = iol.m_product_id)
where mp.m_product_category_id= 1000447 AND mi.issotrx = 'Y';
Please help me out
For me it looks you want to do:
select * from (/*YOUR QUERY*/) where rn = 1;

Top 3 Max Score for each section SQL Developer

I looked at the other questions related to this but it did not work. I even played around with Dense_Rank and still couldn't get the right answer.
Using the Oracle Student Scheme Data. I am trying to find the highest 3 grades for each section based on two tables ( NOT the top 3 rows for each sections. )
This is based off the Student and the Grade table from the Student Scheme
I am using the Oracle Developer 10 and it does not look like it takes the LIMIT function. Cause it gives me the error
missing right parenthesis
select
g.SECTION_ID,g.NUMERIC_GRADE, s.First_Name,s.Last_Name
from GRADE g Join Student s
On g.student_ID = s.student_ID
and Grade_Type_Code='MT'
Where numeric_grade in(Select distinct numeric_grade
from grade
order by numeric_grade desc limit 3);
You can use ROWNUM in Oracle:
SELECT g.SECTION_ID,
g.NUMERIC_GRADE,
s.First_Name,
s.Last_Name
FROM grade g
JOIN Student s
ON g.student_ID = s.student_ID
AND Grade_Type_Code='MT'
WHERE numeric_grade in (SELECT numeric_grade
FROM (SELECT DISTINCT numeric_grade
FROM grade
ORDER BY numeric_grade desc)
WHERE ROWNUM <=3);
Solution with dense_rank:
select section_id, numeric_grade, first_name, last_name
from (
select g.section_id, g.numeric_grade, s.First_Name,s.Last_Name,
dense_rank() over (partition by g.section_id
order by g.numeric_grade desc) rnk
from GRADE g
join Student s on g.student_ID = s.student_ID
and Grade_Type_Code='MT' )
where rnk < 4
order by section_id, numeric_grade desc
SQLFiddle demo

Resources