I have two tables, named t_master and t_detail.
The data in the t_detail table corresponds to a record on the master table.
Data of t_master
ID Brand
1 Toyota
2 Honda
Data for the t_detail
DetID ParentID Model
1 1 Corolla 2009
2 1 Corolla 2010
3 1 Corolla 2011
4 2 Civic 2004
5 2 Civic 2006
Now, I want to make a query that should select all rows in the master table and at the same time, select the detail which has the latest ID (max), i.e.
ID Brand DetID ParentID Model
1 Toyota 3 1 Corolla 2011
2 Honda 5 2 Civic 2006
Appreciate your help. Thanks.
Use:
SELECT m.id,
m.brand,
x.detid,
x.parentid,
x.model
FROM T_MASTER m
JOIN T_DETAIL x ON x.parentid = m.id
JOIN (SELECT d.parentid,
MAX(d.detid) AS max_detid
FROM T_DETAIL d
GROUP BY d.parentid) y ON y.max_detid = x.detid
AND y.parentid = x.parentid
SELECT Make.ID, Make.Brand, Model.DetID, Model.Model
FROM t_master Make
INNER JOIN t_detail Model ON Make.ID = Model.ParentID
WHERE
DetID =
(
SELECT MAX(DetID) From t_detail WHERE ParentID = Make.ID
)
Please note that if you have more rows in Master Table and there are no rows in Detail Table that fits , but you still want to show ALL master table rows then you should initiate the below :
( Please note that you have to add 2 more rows to the master table)
for example :
ID Brand
1 Toyota
2 Honda
3 Porsche
4. Volvo
In order to get the following result :
ID BRAND DETID PARENTID MODEL
1 Toyota 3 1 Corolla 2011
2 Honda 5 2 Civic 2006
4 Volvo - - -
3 Porcshe - - -
Then do the following select (a bit different syntax for the ease of Oracle Users) :
SELECT m.id,
m.brand,
x.detid,
x.parentid,
x.model
FROM T_MASTER m,
T_DETAIL x,
(SELECT m.id,NVL(MAX(d.detid),1) AS max_detid
FROM T_DETAIL d, T_MASTER m
WHERE m.id = d.parentid (+)
GROUP BY m.id) y
WHERE m.id = x.parentid (+)
AND y.max_detid = NVL(x.detid,1)
AND y.id = m.id
Related
I have three tables :
field:
f_id
f_start
f_end
1
10
20
2
15
25
3
5
10
person :
p_id
p_name
1
Roger
2
John
3
Alicia
affect :
id
fk_field
fk_person
1
2
1
2
1
2
3
3
3
And I would like to select the dates and the names associated to. Like this
p_name
f_start
f_end
Roger
15
25
John
10
20
Alicia
5
10
I'm new to SQL and I don't know if i have to use JOIN or not... Thanks
You must join all 3 tables on their related columns:
SELECT p.p_name, f.f_start, f.f_end
FROM person p
INNER JOIN affect a ON a.fk_person = p.p_id
INNER JOIN field f ON f.f_id = a.fk_field;
Depending on your requirement you may need LEFT instead of INNER joins, but for this sample data the INNER joins will do.
id cars price
1 bmw
1 corvette
1 mercedes
2 bmw
3 bmw
3 toyota
4 bmw
4 honda
5 lotus
I found this table from another post and just wanted to use it for my question.
Suppose the ids represent owners and they own multiple cars and some owners have the same car.
I want to write a query such that given a number n and an owner(id)
I can return the cars that the owner has and there are a total of n of these cars in the table.
For example if
I'm given id 1 and n = 4 then it will return
bmw
if I'm given id 1 and n = 1 then it will return
corvette
mercedes
I figured out that
select cars from table group by cars having count(cars) = 4
Gives me all the cars that appear 4 times in the table but I want to narrow it down to a car that is owned by a certain car owner.
Thanks for helping
Method 3 :
select * from
(
select f1.*, rownumber() over(partition by f1.car) rang
from yourtable f1
) f2
where f2.rang=4 and f1.id=1
Method 1 :
with totalcar
(
select car, count(*) nb
from yourtable
group by car
)
select * from yourtable f1 inner join totalcar f2 on f1.car=f2.car
where f1.id=1 and f2.nb=4
Method 2 :
select * from yourtable f1
inner join lateral
(
select f2.car
from yourtable f2
where f1.car=f2.car
group by f2.car
having count(*)=4
) f3 on 1=1
where f1.id=1
Performance table:
PerformanceId SingerId MovieId NumberofSongs
1 1 1 2
2 3 1 4
3 2 2 6
4 4 5 3
5 5 5 3
6 2 6 2
7 4 6 5
8 6 4 6
9 6 3 3
10 4 3 4
Singer table:
SingerId SingerName City DOB Gender
1 A Hyderabad 14-Apr-65 M
2 B Chennai 25-May-84 M
3 C Bangalore 14-Sep-78 F
4 D Hyderabad 17-Jan-70 M
5 E Hyderabad 18-Mar-87 F
6 F Bangalore 23-Aug-75 F
Movie table:
MovieId MovieName ReleaseDate
1 AAA 12-Jan-15
2 BBB 19-Sep-12
3 CCC 23-Jul-10
4 DDD 06-Oct-01
5 EEE 08-Nov-05
6 FFF 18-Apr-99
7 GGG 07-Aug-12
I would need to list the MovieId, MovieName in which both Male and Female singers are performed
(list the movieid, moviename in which male and femail singer ie both singer are performed in one movie)
Hi guys please help me out with this query i tried i am not getting exact query
Here's my query:
select * from movies a inner join performance b
on a.movie_id=b.movie_id where b.singer_id in
(select singer_id from singer where gender = 'F') c inner join
(SELECT SINGER_ID FROM SINGER WHERE gender = 'M') d
on c.singer_id=d.singer_id;
First create a view "MOVIE_ANALYSIS" where you'll have a list of all movies and if they've mixed singers or not:
CREATE VIEW MOVIE_ANALYSIS AS SELECT
M.MOVIEID ,
M.MOVIENAME,
(COUNT(DISTINCT S.GENDER) > 1) AS MIXED
FROM MOVIE M
INNER JOIN PERFORMANCE P ON P.MOVIEID = M.MOVIEID
INNER JOIN SINGER S ON S.SINGERID = P.SINGERID
GROUP BY M.MOVIEID ;
Then you'll get your final result with this query:
SELECT * FROM MOVIE_ANALYSIS WHERE MIXED IS TRUE ;
The reason I used an intermediate view is that in several SQL engines, you cannot use the computed "mixed" attribute directly in the same query with a group by. It'll keep insisting that mixed column is missing.
Validated and test on H2. I did not test on Oracle, as I've no access to it.
What you want here is the INTERSECT statement (using Oracle):
select movieId
from performance a
where exists (select 1
from singer b
where A.singerID = b.singerID
and b.gender = 'F')
intersect
select movieId
from performance a
where exists (select 1
from singer b
where A.singerID = b.singerID
and b.gender = 'M');
Then you just join the movie IDs you get back to the Movie table.
INTERSECT will only bring back IDs that are common to both queries (or however many you use).
I have two tables, students and school_year.
students
---------
ID Name
---------
1 ABC
2 XYZ
school_year
-----------
ID student_id grade year
--------------------------
1 1 5 2011
2 1 6 2012
3 2 1 2010
4 2 2 2011
5 2 3 2012
I join them and get this result
select s.*, sy.grade, sy.year
from students s
left join school_year sy
on s.id=sy.student_id
order by s.name
and I get this result
id name grade year
---------------------------
1 ABC 5 2011
1 ABC 6 2012
2 XYZ 1 2010
2 XYZ 2 2011
2 XYZ 3 2012
I would like to join school year table where grade is maximum/highest for the student so the table would look like this.
id name grade year
-------------------------
1 ABC 6 2012
2 XYZ 3 2012
Please help. Thanks.
Try this out:
SELECT s.id, s.name, sy1.grade, sy1.year FROM school_year sy1
LEFT JOIN school_year sy2
ON sy1.student_id = sy2.student_id AND sy1.grade < sy2.grade
JOIN students s ON sy1.student_id = s.id
WHERE sy2.grade IS NULL
Fiddle here.
I have a self-referencing table with content like this:
Self-referencing parent table
ID ParentID Name
---------------------
1 John
2 1 Mike
3 2 Erin
4 1 Janie
5 Eric
6 5 Peter
The tree hierarchy should look like this
John
Mike
Erin
Janie
Eric
Peter
And a child table that stores the leaf of parent table that looks like this:
ID Sales
3 100
3 100
4 200
4 200
6 300
6 300
6 300
I'm trying to roll-up the sum from the leaf node up to the hierarchy so it would return as ..
ID Name Sum
1 John 800
2 Mike 200
3 Erin 200
4 Janie 400
5 Eric 900
6 Peter 900
Any ideas how to achieve this in sql 2008? Thanks in advance.
EDIT All aggregation moved out of the CTE
WITH
tree AS
(
SELECT
id AS root_id,
name AS root_name,
id AS leaf_id
FROM
yourTreeTable
UNION ALL
SELECT
tree.root_id AS root_id,
tree.name AS root_name,
yourTreeTable.id AS leaf_id
FROM
tree
INNER JOIN
yourTreeTable
ON tree.leaf_id = yourTreeTable.ParentID
)
SELECT
tree.root_id,
tree.root_name,
COALESCE(SUM(yourScoresTable.score), 0) AS total
FROM
tree
LEFT JOIN
yourScoresTable
ON yourScoresTable.ID = tree.leafID
GROUP BY
tree.root_id,
tree.root_name
Here it is:
Let's supose this schema:
​create table #parent (
ID int,
ParentID int,
Name varchar(50) );
create table #child (
ID int,
Sales int );
The query is self explained:
WITH
tree AS
(
SELECT
id as id_parent,
id as id
FROM
#parent
UNION ALL
SELECT
tree.id_parent as id_parent,
#parent.id AS id
FROM
tree
INNER JOIN
#parent
ON tree.id = #parent.ParentID
)
SELECT
#parent.id,
#parent.name,
COALESCE(SUM(#child.Sales), 0) AS total
FROM
#parent
LEFT JOIN
tree
ON #parent.ID = tree.id_parent
LEFT JOIN
#child on tree.id = #child.id
GROUP BY
#parent.id,
#parent.name
CTE returns a list of 'leafs' for each employee (#parent), then query sums all sales for this 'leafs'. You can test it running.
EDITED
Query is fixed.