How to use aggregate function without GROUP BY? - sql

SQL> SELECT * FROM student;
NAME ID AGE MARK1 MARK2 TOTAL
-------------------- ---------- ---------- ---------- ---------- -----------
Ananda 200 22 90 95
Chris 250 18 80 75
Gokul 325 17 50 50
SQL> SELECT MAX(mark1),name FROM student;
SELECT MAX(mark1),name FROM student
*
ERROR at line 1:
ORA-00937: not a single-group group function
As you can see the error,
can anyone suggest me a query to select the Maximum mark from the table
and display it along with the corresponding name of the student??
Is it even possible without using GROUP BY clause?
As you can see, there's no logical way of using GROUP BY clause here.

If you want to get the name of the student also, you need to use a join:
SELECT T2.Mark,T1.name
FROM student T1 JOIN
(SELECT MAX(Mark1) as Mark
FROM student) T2 on T1.Mark=T2.mark
Result:
MAXMARK NAME
------------
90 Ananda
Sample result in SQL Fiddle

If am not wrong you just need Order by and ROWNUM
select * from
(
SELECT mark1,name FROM student Order by Mark1 desc
)
Where ROWNUM = 1
or You can use Analytic functions
select * from
(
SELECT Row_number()over(order by Mark1 desc) as RN,mark1,name FROM student
)
Where RN = 1.
If there is a tie in max mark and you want all the rows with max marks then use Dense_Rank instead of Row_number

I found an easy solution:
SELECT mark1,name
FROM student
WHERE mark1=
(SELECT MAX(mark1) FROM student);
Result:
MARK1 NAME
----- -------
90 Ananda

Related

How to use FIND_IN_SET and sum column in my SQL query

Can anyone help me? I have a table result like this:
id_user
score
type
001
30
play
001
40
play
001
30
redeem
002
20
play
002
30
redeem
I want to sum column score group by id_user base on type 'play' and after that I want show ranking using find_in_set. Like this is the result of the table that I want to display:
id_user
total
rank
001
70
1
002
20
2
Previously I used the rank() function in MySQL version 10.4, but it does not work in MySQL version 15.1. This is my previous query:
SELECT id_user, SUM(score) AS total,
RANK() OVER (ORDER BY total DESC) AS rank
FROM result
WHERE type='play'
GROUP BY id_user
I have made some changes in your query. It's working now. Instead of column alias total SUM(score) needs to be used in order by clause of Rank() function's over(). And since Rank is a reserve word I used rnk instead.
DB-Fiddle:
create table result (id_user varchar(5), score int, type varchar(20));
insert into result values('001',30 ,'play');
insert into result values('001',40 ,'play');
insert into result values('001',30 ,'redeem');
insert into result values('002',20 ,'play');
insert into result values('002',30 ',redeem');
Query:
select id_user, SUM(score) AS total, RANK() OVER (ORDER BY SUM(score) DESC) AS rnk FROM result where type='play' GROUP BY id_user
Output:
id_user
total
rnk
001
70
1
002
20
2
db<>fiddle here
If your MySQL version doesn't support rank() you can use subquery to achieve same result:
Query:
select id_user, SUM(score) AS total,
coalesce((select count(distinct id_user) from result r2
where type='play'
group by id_user
having sum(r2.score)>sum(r.score) ),0)+1 AS rnk
FROM result r where type='play'
GROUP BY id_user
Output:
id_user
total
rnk
001
70
1
002
20
2
db<>fiddle here

SQL Group by sum

id group sal
----------------
3 a 1000
3 b 500
2 c 2000
I need the result like this.
id sum
-------
3 1500
2 2000
SELECT id
, SUM(sal) 'sum'
FROM yourtablename
GROUP BY id;
I think you're looking for something like this.
You could group by the id and sum the sal:
SELECT id, SUM(sal)
FROM sometable
GROUP BY id

Is it possible to SELECT N first rows from database using ROWNUM if some rows have the same value?

I'm trying to select N first rows from a database using ROWNUM. The problem is that if I want to select 6 first values of age with names of people with this age and some of the have the same value of age not every person will be shown.
For example
name age
Peter 15
Mark 22
Kelly 17
Mike 17
George 17
If I want to show people with 2 biggest values of age ROWNUM will show Mark and Kelly or Mike or George. Not all three of them. The expected result is:
Name age
Mark 22
Kelly 17
Mike 17
George 17
Is it possible to get this result using ROWNUM? Not RANK, DENSE_RANK, JOIN, correlated subquery but ROWNUM?
You can try something like this:
select *
from test
where age in (
select age
from (
select age
from test
group by age
order by age desc
)
where rownum <=2
)
The right solution dense_rank(), but you can do it with just row_number() and some subqueries:
select t.*
from t
where t.age in (select age
from (select age
from t t2
order by age desc
) x
where rownum <= 2
);
In Oracle 12+, you can simplify this:
select t.*
from t
where t.age in (select age
from t t2
order by age desc
fetch first 2 rows only
);

How can I create a temporary sequence column in my sql query result?

I have a table which looks like this.
NAME AGE
james 22
ames 12
messi 32
....
....
I can query this table using Select name, age from emp;
Now what I want is having an extra column before name which will be 1,2,3..N if the query return n rows.
SEQUENCE NAME AGE
1 james 22
2 ames 12
3 messi 32
4 ....
....
How I can do this?
if you want to just add a column which will contain sequence number at display time(not actually store that data in a table) you can use ROWNUM pseudocolumn or row_number() analytical function.
select row_number() over(order by name) seq
, name
, age
from your_table
SEQ NAME AGE
---------- ----------- ----------
1 ames 12
2 james 22
3 messi 32
The output of the above query is ordered by NAME but you can order by any column or combination of columns you want.
Second approach is using rownum pseudocolumn. result is ordered by name also
select rownum seq
, name
, age
from ( select name
, age
from your_table
order by name
)
SEQ NAME AGE
---------- ----------- ----------
1 ames 12
2 james 22
3 messi 32
you can try
Select ROWNUM sequence, name , age from emp;
For each row returned by a query, the ROWNUM pseudocolumn returns a number indicating the order in which Oracle selects the row from a table or set of joined rows. The first row selected has a ROWNUM of 1, the second has 2, and so on.

oracle sql query to display one row for each deptid

Guys i want to write an oracle sql query for table A of the following records
--------------------------
R_ID D_ID DEPT
---------------------------
1 200 CLERK
1 50 CLERK
2 190 MANAGER
2 134 DPTY MANAGER
3 12 SERVICE MANAGER
and the result should be like below , ie the first row in all the R_ID
--------------------------
R_ID D_ID DEPT
---------------------------
1 200 CLERK
2 190 MANAGER
3 12 SERVICE MANAGER
kindly help me.
As Ronnis mentioned, I'm not sure how you are ordering the rows, but this is how you would do it in general. Note just substitute the correct ordering in the ORDER BY clauses.
SELECT DISTINCT R_ID
, first_value(D_ID) over (partition by R_ID order by D_ID) D_ID
, first_value(DEPT) over (partition by R_ID order by D_ID) DEPT
FROM your_table
ORDER BY R_ID;
Hope this helps!
SELECT R_ID, D_ID, DEPT
FROM
(
SELECT R_ID, D_ID, DEPT, ROW_NUMBER() over(partition by R_ID order by D_ID) r
) WHERE R=1
SELECT min(r_id), min(d_id), dept
FROM the_table_with_no_name
GROUP BY dept;