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;
Related
I have a table MOVIE containing this data.
MOVIE_ID MOVIE_TITLE CATEGORY SALES_AMT
--------- ------------------------ --------------- ----------
M_0000004 The Boss Baby Animation 2000
M_0000006 Star Wars: The Last Jedi Science Fiction 3000
M_0000007 Get Out Horror 4000
M_0000008 Million Dollar Arm Action 2000
M_0000009 The Conjuring Horror 1000
M_0000012 The Dark Knight Action 3000
I need the Top movies data based on SALES_AMT with respect to CATEGORY
The required result is this:
MOVIE_ID MOVIE_TITLE CATEGORY SALES_AMT
--------- ------------------------ --------------- ----------
M_0000004 The Boss Baby Animation 2000
M_0000006 Star Wars: The Last Jedi Science Fiction 3000
M_0000007 Get Out Horror 4000
M_0000012 The Dark Knight Action 3000
If I use GROUP_BY option, I cannot select MOVIE_ID and MOVIE_TITLE
select CATEGORY, MAX(SALES_AMT)
from MOVIE
group by CATEGORY
;
Try with analytic functions and subquery
select movie_id, movie_title, category, sales_amt
from (
select movie_id, movie_title, category, sales_amt,
row_number() over (partition by category order by sales_amt desc) r
from movie
) where r = 1
You can use RANK() to achieve this:
SELECT
MOVIE_ID
, MOVIE_TITLE
, CATEGORY
, SALES_AMT
FROM
(
SELECT
MOVIE_ID
, MOVIE_TITLE
, CATEGORY
, SALES_AMT
, RANK() OVER (PARTITION BY CATEGORY ORDER BY SALES_AMT DESC) RNK
FROM MOVIE
) Q
WHERE RNK = 1
This would be if you wanted to see duplicates in your results (where sales amounts were equal), otherwise, replace RANK with ROW_NUMBER.
Let's say you run this first:
SQL> select deptno, min(sal)
2 from emp
3 group by deptno;
and then want to get the employee who has that minimum salary. Then this of course fails:
SQL> select deptno, empno, min(sal)
2 from emp
3 group by deptno;
ORA-00979: not a GROUP BY expression
But you can use the KEEP syntax with a window function to assist
SQL> select deptno, min(sal), min(empno)
2 KEEP ( dense_rank FIRST order by sal) empno
3 from emp
4 group by deptno
5 /
DEPTNO MIN(SAL) EMPNO
---------- ---------- ----------
10 1300 7934
20 800 7369
30 950 7900
where this is read as "EMPNO 7934 is the person who has the salary of 1300"
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
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
Folks,
All am looking for is to extend the INNER JOIN. Let me just get to the point. I have two tables Dept & Emp. One Dept can have multiple Emp's & not the other way around.
Table Dept
Dept_id Dept_Name
1 IT
2 HR
3 Other
Table Emp
Emp_id Dept_id Emp_Name
11 1 John
12 1 Jill
13 2 Jack
14 3 Jared
15 1 Jim
16 1 Jarret
17 2 Jacob
I need to JOIN it on Dept_id
Expected Results
Dept_id Dept_name Emp_id Emp_Name
1 IT 11 John
NULL NULL 12 Jill
NULL NULL 15 Jim
NULL NULL 16 Jarret
2 HR 13 Jack
NULL NULL 17 Jacob
3 Other 14 Jared
Hope I conveyed what i want precisely. Its just a regular Inner Join on a Foreign Key Constraint. But, I want the values from the First Table (Dept) to be NULL-ed except for the First Match. That being said, I don't care what's the first match. See it below - Just the result for the Dept_id 1.
Expected Results (Only for Dept_id = 1)
It could be
Dept_id Dept_name Emp_id Emp_Name
1 IT 11 John
NULL NULL 12 Jill
NULL NULL 15 Jim
NULL NULL 16 Jarret
OR
Dept_id Dept_name Emp_id Emp_Name
1 IT 15 Jim
NULL NULL 12 Jill
NULL NULL 11 John
NULL NULL 16 Jarret
OR
Two other possibilities.
Thanks in advance. Sorry for the long explanation even though its a simple case.
I agree with Ic. that this is a crazy query that seems to be doing something that your application should be doing instead of your sql query, that being said, it's fun to write those queries :)
SELECT CASE WHEN RowNumber = 1 THEN Dept_id ELSE NULL END AS Dept_id,
CASE WHEN RowNumber = 1 THEN Dept_name ELSE NULL END AS Dept_name,
Emp_id, Emp_Name
FROM Dept d
INNER JOIN
(SELECT ROW_NUMBER() OVER (PARTITION BY Dept_id ORDER BY Emp_Name) AS RowNumber,
Dept_id, Dept_name, Emp_id, Emp_Name
FROM Emp ) t on t.Dept_id = d. Dept_id
select case
when lag(d.dept_id) over (partition by d.dept_id order by e.emp_id) = d.dept_id then null
else d.dept_id
end as dept_id,
case
when lag(d.dept_name) over (partition by d.dept_id order by e.emp_id) = d.dept_name then null
else d.dept_name
end as dept_name,
e.emp_id,
e.emp_name
from dept d
join emp e on e.dept_id = d.dept_id
order by d.dept_id, d.dept_name, e.emp_id
Honestly, I'm not really sure why you want this result. Formatting is usually best left for the UI layer and NOT your database server. Doing it this way makes the data look like the non-first-employees for each department actually do not have a department, and it fundamentally breaks any sorting or editing functions you may have in your client.
However, you could try:
SELECT FormattedDept.Dept_id, FormattedDept.Dept_Name, Emp.Emp_id, Emp.Emp_Name
FROM Emp
LEFT OUTER JOIN
(
SELECT Dept.Dept_id, Dept.Dept_Name, MIN(Emp_id) AS Emp_id
FROM Dept
INNER JOIN Emp ON Dept.Dept_id = Emp.Dept_id
GROUP BY Dept.Dept_id, Dept.Dept_Name
) FormattedDept ON Emp.Dept_id = FormattedDept.Dept_id
AND Emp.Emp_id = FormattedDept.Emp_id
ORDER BY Emp.Dept_id, Emp.Emp_id
SQL Fiddle Demo
As I mention in my comment above, I'm not sure that you would really want the results to return in the way you are asking. Consider this. If the result set was exported to Excel, and a user changed the sort, then you would lose what dept employee 1-x was in and employee 0 would still show their department. I would suggest you group by Dept_id, and not null out the dept_id and dept_name. Handle the display of that data in your display code.
WITH newRecord
AS
(
SELECT "Emp_id", "Dept_id", "Emp_Name",
ROW_NUMBER() OVER (PARTITION BY "Dept_id" ORDER BY "Emp_id" ASC) RN
FROM Emp
)
SELECT CASE WHEN RN = 1 THEN b."Dept_id" ELSE NULL END AS "Dept_ID",
CASE WHEN RN = 1 THEN b."Dept_Name" ELSE NULL END AS "Dept_Name",
"Emp_id", "Emp_Name"
FROM newRecord a
INNER JOIN Dept b ON a."Dept_id" = b."Dept_id"
SQLFiddle Demo
because i cant think of a reason you would want that other then reporting purposes then you can also do this by using SQL*Plus formmating.
just run the following command before the query in SQL*Plus
break on dept_id skip 1
Enjoy.
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.