SQL select with three tables and foreign keys - sql

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.

Related

I want movie name from the given database

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).

Access - Join two tables on two fields, get all records from table A

OK, so in MS Access I am trying to join two tables on two fields (customer ID and product type), have table A use a sum of each product type, and have all the records from table A so I can know what is missing from table B.
In table A, there are multiple records for each customer for each product type by year. But in table B there is only one record per product type. And in table B not all the product types are there.
Example Tables:
Table A:
Cust ID ProdType Year Number
1 A 2014 5
1 A 2013 8
1 B 2014 3
2 A 2014 13
2 C 2014 2
3 B 2014 1
3 C 2014 4
Table B:
Number
Cust ID ProdType Arrived
1 A 5
2 A 13
2 C 2
3 B 1
3 C 2
Final Result should look like:
Sum of Number
Cust ID ProdType Number Arrived
1 A 13 5
1 B 3
2 A 13 13
2 C 2 2
3 A 1 1
3 C 4 2
Try this,
MySQL Syntax
select a.cust_id, a.prodtype, sum(a.number), b.arrived
from table_a a left join table_b b on a.cust_id=b.cust_id and a.prodtype=b.prodtype
group by a.cust_id, a.prodtype
Here is DEMO (MySQL)
Ms-Access
select a.cust_id, a.prodtype, sum(a.number), b.arrived
from table_a a left join table_b b
on a.cust_id=b.cust_id and
on a.prodtype=b.prodtype
group by a.cust_id, a.prodtype

Using multiple joins (e.g left join)

I would like to know what's the logic for multiple joins (for example below)
SELECT * FROM B returns 100 rows
SELECT B.* FROM B LEFT JOIN C ON B.ID = C.ID returns 120 rows
As I know using left join will returns any matching data from the left table which is B if data are found for both table. But how come when using left join, it returns more data than table B itself?
What am I do wrong or misunderstood here? Any guidance are very appreciated. Thanks in advance.
Let be table B:
id
----
1
2
3
Let be table C
id name
------------
1 John
2 Mary
2 Anne
3 Stef
Any id from b is matched with ids from c, then id=2 will be matched twice. So a left join on id will return 4 rows even if base table B has 3 rows.
Now look at a more evil example:
Table B
id
----
1
2
2
3
4
table C
id name
------------
1 John
2 Mary
2 Anne
3 Stef
Every id from b is matched with ids from c, then first id=2 will be matched twice and second id=2 will be matched twice so the result of
select b.id, c.name
from b left join c on (b.id = c.id)
will be
id name
------------
1 John
2 Mary
2 Mary
2 Anne
2 Anne
3 Stef
4 (null)
The id=4 is not matched but appears in the result because is a left join.
Look at the following example :
B = {1,2}
C = {(1,a),(1,b),(1,c),(1,d),(1,e)}
The result of B left join C will be :
1 | a
1 | b
1 | c
1 | d
1 | e
2 | null
The number of rows in the result is definitely larger than rows in B (2).
In general the number of rows in result of B left join C is bounded by B.size + C.size and not only by B.size as you think...
As per your query it do the join to B Table with C and B table is Left Table so it will display all the records of Left table in our case it is B and related from other Table in our Case it is C.

id getting duplicate PV.RFMID [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how can i use distinct INNER JOIN RFM ON RFM.RFMID=PV.RFMID
Table MMASTER
MID col1
1 abc
2 xyx
3 pqr
Table AMM
AMMID MID col1 col2
1 1 bnb mfk
2 1 def rwr
3 2 re wrwr
Table PS
UID VTID AMMID SMID col1 col2
1 1 1 1 rkk jdj
2 2 3 3 kdf lfl
6 2 2 4 rgr rtr
Table PV
VTID PMID RFMID
1 2 1
2 2 3
7 2 2
Table RFM
RFMID title name
1 mr john
2 mr jack
3 mr jim
Table PM
PMID col1 col2
1 df ere
2 rwe rwer
3 rwr fwr
Table SM
SMID MMID col1 col2
1 1 fdf efe
2 1 ddf dfdf
3 2 df ef
I get result like this after fire above query
PMID title name PV.RFMID
2 mr. jim 3
2 mr. jim 3
2 mr. jim 3
***BUT RESULT SHOULD BE LIKE THIS***
PMID title name PV.RFMID
2 mr. john 1
2 mr. jim 3
2 mr. jack 2
In my query PV.RFMID getting duplicate value when join with RFM and due to that title and name getting duplicate
This will give you your desired Output:
select pm.pmid, rfm.title, rfm.name, pv.rfmid from PM as PM
inner join PV on pm.pmid = pv.pmid
inner join RFM as rfm on pv.rfmid = rfm.rfmid
WHERE PM.PMID='2'
EDIT
Considering that you need to Join all tables, it's something tricky.
I mean, checking RFMtable, you can see the RFMId, related to PV table, and see that the VTID has a 7 value.. which is not related to anything ! So, if you need to join all tables, you won't get that result
I Am assuming that table "PM" is your transaction table where one "PMID" can have multiple Entries, thus Adding a Distinct Clause Before your Query will Get you the Desired Out Put.
Try This:
SELECT DISTINCT PM.PMID,RFM.TITLE,RFM.NAME ,PV.RFMID FROM MMASTER
INNER JOIN AMM ON MMASTER.MID=AMM.MID
INNER JOIN PS ON AMM.AMMID=PS.AMMID
INNER JOIN PV ON PV.VTID=PS.VTID
INNER JOIN RFM ON RFM.RFMID=PV.RFMID
INNER JOIN PM ON PV.PMID=PM.PMID
INNER JOIN SM ON PS.SMID=SM.SMID
WHERE PM.PMID='2'

How to count linked entries in another table with a specific value

Let's say I have two tables. A students table and an observations table. If the students table looks like:
Id Student Grade
1 Alex 3
2 Barney 3
3 Cara 4
4 Diana 4
And the observations table looks like:
Id Student_Id Observation_Type
1 1 A
2 1 B
3 3 A
4 2 A
5 4 B
6 3 A
7 2 B
8 4 B
9 1 A
Basically, the result I'd like from the query would be the following:
Student Grade Observation_A_Count
Alex 3 2
Barney 3 1
Cara 4 2
Diana 4 0
In other words, I'd like to gather data for each student from the students table and for each student count the number of A observations from the observations table and tack that onto the other information. How do I go about doing this?
This is a simple join and aggregate:
select
a.Student,
a.Grade,
count(b.Id) as Observation_A_Count
from
Student a left join
Observations b on a.Id = b.Student_Id
group by
a.Student,
a.Grade
order by
1
Or, you can use a correlated subquery:
select
a.Student,
a.Grade,
(select count(*) from observations x where x.Student_Id = a.Id) as Observation_A_Count
from
Student a
order by
a.Student
You can join the table with a specific condition, by doing this you can have a field for Observation_B_Count and Observation_C_Count, etc.
SELECT Student.Student, Student.Grade, COUNT(Observation_Type.*) AS Observation_A_Count
FROM Student
LEFT JOIN Observations ON Observations.Student_ID = Student.Student_ID AND Observations.Observation_Type = 'A'
GROUP BY Student.Student, Student.Grade