How to write a single query for the below scenario? - sql

I am new to SQL and I am facing a problem in writing a query for one scenario. I have 3 tables:
Table 1 has actor names and movie-id's
Table1
Actor-ID Actor-name Movies_id
Table 2 has movie-id's and corresponding movie names.
Table2
Movies_id Movies_name
Table 3 has movie-id's and corresponding revenue generated by the movies.
Table3
Movies_id Revenue_generated
I want to write a query to fetch data for the below scenario:
All the movies of any one actor which has earned more than 100 crores.
I haven't mention any data in the tables, so feel free to add data from your side.

You should re-design the database with these tables:
actor (actor_id, name)
movie (movie_id, name, revenue)
actor_movie (actor_id, movie_id)
And the query would be:
select *
from movie
where revenue > 1000000000
and movie_id in
(
select movie_id
from actor_movie
where actor_id = (select actor_id from actor where name = 'Bruce Willis')
);

Data :
INSERT [dbo].[Table1] ([Actor_ID], [Actor_Name], [Movies_ID]) VALUES
(1, N'A1', 2),
(2, N'A2', 1),
(3, N'A3', 3),
(3, N'A3', 4),
(2, N'A2', 6)
INSERT [dbo].[Table2] ([Movies_ID], [Movies_Name]) VALUES
(1, N'M1'),
(2, N'M2'),
(3, N'M3')
(4, N'M4'),
(5, N'M5'),
(6, N'M6')
INSERT [dbo].[Table3] ([Movies_ID], [Revenue_generated]) VALUES
(1, 50),
(2, 100),
(3, 150),
(4, 75),
(5, 120),
(6, 115)
query :
Select
a.Actor_name,
b.Movies_name,
c.Revenue_generated
from
Table1 a
inner join Table2 b on a.Movies_ID = b.Movies_ID
inner join Table3 c on b.Movies_ID = c.Movies_ID
where c.Revenue_generated > 100 AND a.Actor_Name= 'A1'
replace 100 with desired value.

This will help you out.
SELECT
A.Actor-name,B.Movies_name
FROM
table1 A INNER JOIN table2 ON
A.Movies_id= B.Movies_id
INNER JOIN table3 C ON
A.Movies_id= C.Movies_id
WHERE C.Revenue_generated > 10000000000

Related

How many elements in one column are linked to an element other column?

Consider I have two tables
Courses Program
---------------------------
course_ID program_id
course_title program_name
program_ID
Now, I want to check no of courses(by course_id) offered by each program (program_id).
select c.program_id ,p.program_name, count(course_id)
from courses c
join Program p on c.Program_id =p.Program_id
group by program_id,program_name
If I understood you correctly, you're searching for a GROUP BY and a corresponding aggregate.
--Creating sample tables and data
SELECT course_ID, course_title, program_ID
INTO #courses
FROM (
VALUES (0, 'course_0', 0),
(1, 'course_1', 0),
(2, 'course_2', 0),
(3, 'course_3', 0),
(4, 'course_4', 1),
(5, 'course_5', 1),
(NULL, 'course_6', 1)
) AS C (course_ID, course_title, program_ID)
SELECT program_ID, program_title
INTO #programs
FROM (
VALUES (0, 'program_0'),
(1, 'program_1')
) AS P (program_ID, program_title)
and after that execute the query
SELECT P.program_title, COUNT(C.course_ID) AS courses_amount
FROM #courses C
INNER JOIN #programs P ON C.program_ID = P.program_ID
GROUP BY P.program_ID, P.program_title
So you basically GROUP BY the value to which you to aggregate to and COUNT the 'course_id'.
COUNT(C.course_ID) only counts actual values and will ignore NULLs.
If you want to count the NULLs as well, just use COUNT(*).
EDIT: Forgot the result...
So it'll look like this:
program_title
courses_amount
program_0
4
program_1
2

Aggregation Sum in SQL (Joins)

I'm having some trouble with summing some column in my query with aggregation.
It's a bit difficult to describe what is happening but I'll try my best:
I have 3 tables - details, extra details and places.
Places is a table that contains places in the world. Details contains details about events that happened, and extra details provides some more data on the events. Each place has an ID and a ParentID (Like New York has an ID and it's parent ID is the US. Something like that). The ID of the event(details) appears a number of times as a column in the extra details table. The extra details table also holds the ID of the place that that event occurred at.
OK after all of that, what I'm trying to achieve is, for each place, the sum of the events that happened there. I know it sounds very specific, but it's what the client asked. Anyhow, example of what I'm trying to get to:
NewYork 60, Chicago 20, Houston 10 Then the US will have 90. And it has several levels.
So this is what I was trying to do:
With C(ID, NAME, COUNTT, ROOT_ID) as
(
SELECT d.ID, d.NAME,
(SELECT COUNT(LX.ID) as COUNTT
FROM EXTRA LX
RIGHT JOIN d ON LX.PLACE_ID = d.ID -- ****
GROUP BY d.ID, d.NAME),
d.ID as ROOT_ID
FROM PLACES d
UNION ALL
SELECT d.ID, d.NAME,
(SELECT COUNT(LX.ID) as COUNTT
FROM EXTRA LX
RIGHT JOIN d ON LX.PLACE_ID = d.ID
GROUP BY d.ID, d.NAME),
C.ROOT_ID
FROM PLACES dx
INNER JOIN C ON dx.PARENT_ID = C.ID
)
SELECT p.ID, p.NAME, S.SumIncludingChildren
FROM places p
INNER JOIN (
SELECT ROOT_ID, SUM(COUNTT) as SumIncludingChildren
FROM C
GROUP BY ROOT_ID
) S
ON p.ID = S.ROOT_ID
ORDER BY p.ID;
The details table is only for showing their data. I'll add that later. It's only comparing the respective columns. To making it work I don't need that. Only for the site data.
It doesn't work because it doesn't recognizes the 'd' where the '****' is. If I'll put a 'new instance' of that table, it won't work either. So I tried to replicate what the right join by doing 'NOT EXISTS IN' on a query that gets all the places instead of the right join...on. Same problem.
Maybe I don't get something. But I'm really seeking a solution and some explanation. I know my code isn't perfect.
Thanks in advance.
EDIT: I'm using OracleSQL on Toad 10.6
create table p(id number, up number, name varchar2(100));
create table e(id number, pid number, dsc varchar2(100));
insert into p values (1, null, 'country');
insert into p values (2, 1, 'center');
insert into p values (3, 1, 'province');
insert into p values (4, 2, 'capital');
insert into p values (5, 2, 'suburb');
insert into p values (6, 3, 'forest');
insert into p values (7, 3, 'village');
insert into p values (8, 7, 'shed');
insert into p values (9, 2, 'gov');
insert into e values (1, 8, 'moo');
insert into e values (2, 8, 'clank');
insert into e values (3, 7, 'sowing');
insert into e values (4, 6, 'shot');
insert into e values (5, 6, 'felling');
insert into e values (6, 5, 'train');
insert into e values (7, 5, 'cottage');
insert into e values (8, 5, 'rest');
insert into e values (9, 4, 'president');
insert into e values (10,1, 'GNP');
commit;
with
places as
(select id,
up,
connect_by_root id as root,
level lvl
from p
connect by prior id = up),
ev_stats as
(select root as place, max(lvl) as max_lvl, count(e.id) as ev_count
from places left outer join e
on places.id = e.pid
group by root)
select max_lvl, p.name, ev_count
from ev_stats inner join p on p.id = ev_stats.place
order by max_lvl desc;

SQL connecting table and comparing value in same column

Hello I have these two tables:
Team:
team_id
team_name
division
and
Match:
match_id
match_date
...
Team_team_id
Team_team_id1
Example of the Team data:
(1, Anaheim, P)
(2, Arizona, P)
(3, Boston, S)
(4, Buffalo, M)
(5, Detroit, M)
and Match:
(1, date, 1, 2)
(2, date, 2, 3)
(3, date, 5, 3)
and result should be only Anaheim(played against Arizona in same division)
I want to list only team's names, which played matches only against teams in the same division. How could I do that in SQL and relational algebra? Division is only character value. Thank you for any help...
SELECT t1.team_name AS team_name1,
t2.team_name AS team_name2
FROM team t1
INNER JOIN match m
ON ( t1.team_id = m.team_team_id )
INNER JOIN team t2
ON ( t2.team_id = m.team_team_id1 )
WHERE t1.division = t2.division

PostgreSQL: Get an entity with all his relationships

I have a table "Cars" and a table "Person". A Person drives many Cars and a Car can be driven by many People so I have another table "Person_Car" which has both id's per row.
Car(id, name)
Person(id, name)
Person_Car(car_id, person_id)
How can I get a list of all people with the cars it drives (car names concatenated), something like this:
("John", "Car 1, Car 2, Car 3")
("Kate", "Car 2, Car 4, Car 5")
Example is here: http://sqlfiddle.com/#!15/ba949/1
Test data:
Create table Car(id int, name text);
Create table Person(id int, name text);
Create table Person_Car(car_id int, person_id int);
INSERT INTO Car VALUES (1, 'Car 1'),
(2, 'Car 2'),
(3, 'Car 3'),
(4, 'Car 4'),
(5, 'Car 5');
INSERT INTO Person VALUES(1, 'John'), (2, 'Kate');
INSERT INTO Person_Car VALUES (1,1), (2,1), (3,1), (2,2), (4,2), (5,2);
Your desired code:
SELECT p.name, array_to_string(array_agg(c.name), ',') FROM Person p
INNER JOIN Person_Car pc ON p.id=pc.person_id
INNER JOIN Car c ON c.id=pc.car_id
GROUP by p.name
Output:
John Car 1,Car 2,Car 3
Kate Car 2,Car 4,Car 5
Just in case you want to avoid the GROUP BY
Option 1
WITH forienKeyTable AS
(
SELECT pc.person_id, c.name
FROM Car c
JOIN Person_Car pc ON pc.car_id = c.id
)
SELECT p.name
, array_to_string
(ARRAY(
SELECT fkt.name
FROM forienKeyTable fkt
WHERE fkt.person_id = p.id
)::text[], ','::text, 'empty'::text)
FROM Person p;
Option 2
SELECT p.name
, array_to_string
(ARRAY(
SELECT c.name
FROM Car c
JOIN Person_Car pc ON pc.car_id = c.id
WHERE pc.person_id = p.id
)::text[], ','::text, 'empty'::text)
FROM Person p;

how to do get multiple columns + count in a single query?

I usually don't ask for "scripts" but for mechanisms but I think that in this case if i'll see an example I would understand the principal.
I have three tables as shown below:
and I want to get the columns from all three, plus a count of the number of episodes in each series and to get a result like this:
Currently, I am opening multiple DB threads and I am afraid that as I get more visitors on my site it will eventually respond really slowly.
Any ideas?
Thanks a lot!
First join all the tables together to get the columns. Then, to get a count, use a window function:
SELECT count(*) over (partition by seriesID) as NumEpisodesInSeries,
st.SeriesId, st.SeriesName, et.episodeID, et.episodeName,
ct.createdID, ct.CreatorName
FROM series_table st join
episode_table et
ON et.ofSeries = st.seriesID join
creator_table ct
ON ct.creatorID = st.byCreator;
Do your appropriate joins between the tables and their IDs as you would expect, and also join onto the result of a subquery that determines the total episode count using the Episodes table.
SELECT SeriesCount.NumEpisodes AS #OfEpisodesInSeries,
S.id AS SeriesId,
S.name AS SeriesName,
E.id AS EpisodeId,
E.name AS EpisodeName,
C.id AS CreatorId,
C.name AS CreatorName
FROM
Series S
INNER JOIN
Episodes E
ON E.seriesId = S.id
INNER JOIN
Creators C
ON S.creatorId = C.id
INNER JOIN
(
SELECT seriesId, COUNT(id) AS NumEpisodes
FROM Episodes
GROUP BY seriesId
) SeriesCount
ON SeriesCount.seriesId = S.id
SQL Fiddle Schema:
CREATE TABLE Series (id int, name varchar(20), creatorId int)
INSERT INTO Series VALUES(1, 'Friends', 1)
INSERT INTO Series VALUES(2, 'Family Guy', 2)
INSERT INTO Series VALUES(3, 'The Tonight Show', 1)
CREATE TABLE Episodes (id int, name varchar(20), seriesId int)
INSERT INTO Episodes VALUES(1, 'Joey', 1)
INSERT INTO Episodes VALUES(2, 'Ross', 1)
INSERT INTO Episodes VALUES(3, 'Phoebe', 1)
INSERT INTO Episodes VALUES(4, 'Stewie', 2)
INSERT INTO Episodes VALUES(5, 'Kevin Kostner', 3)
INSERT INTO Episodes VALUES(6, 'Brad Pitt', 3)
INSERT INTO Episodes VALUES(7, 'Tom Hanks', 3)
INSERT INTO Episodes VALUES(8, 'Morgan Freeman', 3)
CREATE TABLE Creators (id int, name varchar(20))
INSERT INTO Creators VALUES(1, 'Some Guy')
INSERT INTO Creators VALUES(2, 'Seth McFarlane')
Try this:
http://www.sqlfiddle.com/#!3/5f938/17
select min(ec.num) as NumEpisodes,s.Id,S.Name,
Ep.ID as EpisodeID,Ep.name as EpisodeName,
C.ID as CreatorID,C.Name as CreatorName
from Episodes ep
join Series s on s.Id=ep.SeriesID
join Creators c on c.Id=s.CreatorID
join (select seriesId,count(*) as Num from Episodes
group by seriesId) ec on s.id=ec.seriesID
group by s.Id,S.Name,Ep.ID,Ep.name,C.ID,C.Name
Thanks Gordon
I would do the following:
SELECT (SELECT Count(*)
FROM episodetbl e1
WHERE e1.ofseries = s.seriesid) AS "#ofEpisodesInSeries",
s.seriesid,
s.seriesname,
e.episodeid,
e.episodename,
c.creatorid,
c.creatorname
FROM seriestbl s
INNER JOIN creatortbl c
ON s.bycreator = c.creatorid
INNER JOIN episodetbl e
ON e.ofseries = s.seriesid