How to select NOT using SQL JOIN - sql

My question is to select pilots that are currently not assigned to any flight.
My idea is to use LEFT JOIN to select pilots that are currently assigned to flights, then select the null values. Am I right?
I am trying to select the null value by using WHERE...IS NULL, but I don't know how. Thanks for the help.
There are five tables:
Flight:
PRIMARY KEY (id),
FOREIGN KEY (route) REFERENCES Route (id),
FOREIGN KEY (aircraft) REFERENCES Aircraft (id)
Aircraft:
PRIMARY KEY (id),
FOREIGN KEY (aircraftType) REFERENCES AircraftType (id)
AircraftType:
PRIMARY KEY (id)
Pilot:
PRIMARY KEY (person, forAircraftType),
FOREIGN KEY (person) REFERENCES Person (id),
FOREIGN KEY (forAircraftType) REFERENCES AircraftType (id)
Person:
PRIMARY KEY (id)
Here is my code, I can select pilots that are currently assigned to flight
SELECT name
FROM Flight
LEFT JOIN Aircraft ON Flight.aircraft = Aircraft.id
LEFT JOIN AircraftType ON Aircraft.AircraftType = AircraftType.id
LEFT JOIN Pilot ON AircraftType.id = Pilot.forAircraftType
LEFT JOIN Person ON Pilot.person = Person.id

Instead of trying to join your "Flight" table into the query, simply check if the pilot exists in the Flight table:
SELECT name
FROM Aircraft
LEFT JOIN AircraftType
ON Aircraft.AircraftType = AircraftType.id
LEFT JOIN Pilot
ON AircraftType.id = Pilot.forAircraftType
LEFT JOIN Person
ON Pilot.person = Person.id
WHERE NOT EXISTS (SELECT 1 FROM Flight WHERE Flight.aircraft = Aircraft.id)

Reverse your query or use Right Join as opposed to Left. In its current configuration, Flight is your base table that all other tables are being joined to so it will only return records where pilots have been assinged to a flight i.e. this acts a filter which excludes unassigned Pilots.
By making Pilot or Person as your base, you are aligning all other tables to it and can simply use IS NULL to get your results.
SELECT name
FROM Person
LEFT JOIN Pilot ON Person.id = Pilot.person
LEFT JOIN AircraftType ON Pilot.forAircraftType = AircraftType.id
LEFT JOIN Aircraft ON AircraftType.id = Aircraft.AircraftType
LEFT JOIN Flight ON Aircraft.id = Flight.aircraft
Where Flight.aircraft IS NULL

You want to select those rows which are contains null into name field of flight
SELECT name
FROM Flight
LEFT OUTER JOIN Aircraft
ON Flight.aircraft = Aircraft.id
LEFT JOIN AircraftType
ON Aircraft.AircraftType = AircraftType.id
LEFT JOIN Pilot
ON AircraftType.id = Pilot.forAircraftType
LEFT JOIN Person
ON Pilot.person = Person.id
WHERE Flight.name is null

Related

Using inner join as ALIASES with multiple tables

I have these tables below:
create table student(
studentName varchar (40) not null,
studentRollNo varchar (30) primary key, -- also acts as username
studentPassword varchar(30) NOT NULL,
studentGender varchar(7) default NULL
);
create table supervisors(
supervisorID varchar(30) foreign key references Faculty(facultyID) unique,
sWorkLoad int default null,
CHECK (sWorkLoad<=6 and sWorkLoad>=0)
);
create table co_supervisors(
co_supervisorID varchar(30) foreign key references Faculty(facultyID) unique,
csWorkLoad int default null,
CHECK (csWorkLoad<=6 and csWorkLoad>=0)
);
create table studentGroup(
groupID int IDENTITY(1,1) primary key ,
Member1rollNo varchar(30) foreign key references student(studentRollNo) default NULL, -- member 1
Member2rollNo varchar(30) foreign key references student(studentRollNo) default NULL, -- member 2
Member3rollNo varchar(30) foreign key references student(studentRollNo) default NULL, -- member 3
supervID varchar(30) foreign key references supervisors(supervisorID),
co_supervID varchar(30) foreign key references co_supervisors(co_supervisorID) default NULL,
projectTitle varchar(100) not null,
projectDetails varchar (500) default NULL
);
create table FYP1(
groupID int foreign key references studentGroup(groupID),
);
I want to display student details who are registered in FYP1.
with their supervisors, co_supervisors,and project title.
But I I'm not able to do so,
What I have done so far is this.
select sg.Member1rollNo,S.studentName,Member2rollNo,S.studentName,sg.Member3rollNo,sg.supervID,sg.projectTitle
FROM student S
inner join studentGroup SG ON S.studentRollNo = SG.Member1rollNo
OR some random tries like this
-- Faculty.facultyName
SELECT FYP1.groupID, studentGroup.Member1rollNo,student.studentName as student1, studentGroup.Member2rollNo,student.studentName as student2,studentGroup.projectTitle
FROM FYP1 as FYP1_Students
INNER JOIN studentGroup ON (studentGroup.groupID = FYP1_Students.groupID)
INNER JOIN supervisors ON (studentGroup.supervID = supervisors.supervisorID)
INNER JOIN student ON (student1.studentRollNo = studentGroup.Member1rollNo)
INNER JOIN student ON (student.studentRollNo = studentGroup.Member2rollNo)
Output or first query is this (example):
'i19-0434' 'Sourav Malani' 'i19-0498' 'Sourav Malani' NULL 'urooj.ghani' 'Indoor Navigation'
'i19-0466' 'Aftab Ali' 'i19-0528' 'Aftab Ali' NULL 'urooj.ghani' 'AI based Physics exp.'
I want output to be like:
'i19-0434' 'Sourav Malani' 'i19-0498' 'Student2 Name' NULL 'urooj.ghani' 'Indoor Navigation'
'i19-0466' 'Aftab Ali' 'i19-0528' '<student2Name>' NULL 'urooj.ghani' 'AI based Physics exp.'
Sample Data
Thanks to #Hana, I solved the problem.
Here's the solution:
SELECT SG.groupID,
SG.Member1rollNo,S1.studentName as 'student1 Name',
SG.Member2rollNo, S2.studentName as 'student2 Name',
SG.Member3rollNo, S3.studentName as 'Studen3 Name',
SG.supervID, SN.facultyName as 'Supervisor Name',
SG.co_supervID, CSN.facultyName as 'Co_Supervisor',
SG.projectTitle as 'Project Title',
SG.projectDetails as 'Project Desc.'
FROM FYP1 FYP1
LEFT OUTER JOIN studentGroup SG ON FYP1.groupID = SG.groupID
LEFT OUTER JOIN supervisors SV ON SG.supervID = SV.supervisorID
LEFT OUTER JOIN Faculty SN ON SG.supervID= SN.facultyID
LEFT OUTER JOIN Faculty CSN ON SG.co_supervID= CSN.facultyID
LEFT OUTER JOIN student S1 ON SG.Member1rollNo = S1.studentRollNo
LEFT OUTER JOIN student S2 ON SG.Member2rollNo = S2.studentRollNo
LEFT OUTER JOIN student S3 ON SG.Member3rollNo = S3.studentRollNo
Is this what you are looking for?
SELECT SG.groupID, SV.supervisorID, CSV.co_supervisorID, S1.studentName, S2.studentName, S3.studentName
FROM FYP1 FYP1
INNER JOIN studentGroup SG ON FYP1.groupID = SG.groupID
INNER JOIN supervisors SV ON SG.supervID = SV.supervisorID
INNER JOIN co_supervisors CSV ON SG.co_supervID = CSV.co_supervisorID
INNER JOIN student S1 ON SG.Member1rollNo = S1.studentRollNo
INNER JOIN student S2 ON SG.Member1rollNo = S2.studentRollNo
INNER JOIN student S3 ON SG.Member1rollNo = S3.studentRollNo

how Inner join work on two foreign key from single table

I am working on Bus route management system , I made two table first one is Cities and second one is route have following queries
CREATE TABLE Cities
(
ID NUMBER GENERATED ALWAYS AS IDENTITY(START with 1 INCREMENT by 1) PRIMARY KEY,
Name Varchar(30) not null,
)
CREATE TABLE route
(
ID NUMBER GENERATED ALWAYS AS IDENTITY(START with 1 INCREMENT by 1) PRIMARY KEY,
Name Varchar(30) not null,
from NUMBER not null,
to NUMBER NOT NULL,
CONSTRAINT FROM_id_FK FOREIGN KEY(from) REFERENCES Cities(ID),
CONSTRAINT TO_id_FK FOREIGN KEY(to) REFERENCES Cities(ID),
)
i am joining the table through inner join
select CITIES.Name
from CITIES
inner join ROUTES on CITIES.ID=ROUTES.ID
but it show single column as
Name
-----------
but i want result as
from | to
------------------------
what is possible way to do this using inner join
I suspect you need something like the following:
select r.Name, cs.Name SourceCity, cd.Name DestinationCity
from routes r
join cities cs on cs.id = r.from
join cities cd on cd.id = r.to
Hope is working for you
select CITIES.Name,ROUTES.from,ROUTES.to
from CITIES inner join ROUTES on CITIES.ID=ROUTES.ID

Is left outer join equivalent to inner join for non-null foreign keys?

Each city has owning country:
create table COUNTRY
(
ID number not null,
NAME varchar,
primary key (ID)
);
create table CITY
(
ID number not null,
NAME varchar,
COUNTRY_ID number not null,
primary key (ID)
);
alter table CITY
add constraint CITY_COUNTRY_FK
foreign key (COUNTRY_ID) references COUNTRY (ID);
Is the following:
select *
from CITY c
left outer join COUNTRY ctr on ctr.ID = c.COUNTRY_ID
where ...;
equivalent to:
select *
from CITY c
inner join COUNTRY ctr on ctr.ID = c.COUNTRY_ID
where ...;
because COUNTRY_ID is foreign key and not null?
In this case, the left join is redundant based on the data model. The NOT NULL constraint means that every city has a country_id. The foreign key constraint means that the country_ids are valid and are in the country table.
Combined, these constraints say that every row in city has a matching row in country. When all keys match, the left join is equivalent to inner join.
Yes basically if you are sure all entries had an equivalent, at all cases the left will be equivalent to inner.
As you mentioned each city has owning country, so yes it's gonna be the same result

How can I use a join for two columns corresponding to the same primary key?

I have a table with five columns:
streetId, streetName, areaId, ISfSectionId1, ISFsectionId2
where areaId is a foreign key for table area and isfsectionid1 and isfsectionid2 are foreign keys for the same primary key isfsectionId (isfsectionId2 can have null value).
I am using this query to join them
SELECT
s.streetId, s.streetName, a.areaName, i.isfsectionName, d.ISFsectionName
FROM
area a
INNER JOIN
street s ON s.areaId = a.areaId
INNER JOIN
ISFsections i ON s.fasileone = i.ISFsectionId
JOIN
ISFsections d ON s.fasiletwo = d.ISFsectionId
Without that last join, it is working fine, but when adding the last join, it's returning records for the ISFsectionId2 only.
What is the problem?
SELECT s.streetId
,s.streetName
,a.areaName
,i.isfsectionName
,d.ISFsectionName
from area a
INNER join street s on s.areaId = a.areaId
LEFT join ISFsections i on s.fasileone = i.ISFsectionId
LEFT join ISFsections d on s.fasiletwo = d.ISFsectionId

Conditional query of the tables

ALL,
Consider the following database schema:
CREATE TABLE players(playerid integer primary key, playertype integer, ....);
CREATE TABLE scoretype1(scoreid integer primary key, scorename varchar);
CREATE TABLE scoretype2(scoreid integer primary key, scorename varchar);
CREATE TABLE scoreforplayerstype1(playerid integer, scoreid integer, value double, foreign key(playerid) references players(playerid), foreign key(scoreid) references scoretype1(scoreid));
CREATE TAble scoreforplayerstype2(playerid integer, scoreid integer, value double, foreign key(playerid) references players(playerid), foreign key(scoreid) references scoretype2(scoreid));
Now the problem:
Is it possible to get the score values for all players in one query or I have to do 2 queries for type 1 and type 2? I'm looking to have a score name and score value for a player.
Thank you.
SELECT P1.PLAYERID, S1.SCORENAME, J1.VALUE
FROM PLAYERS AS P1
INNER JOIN SCOREFORPLAYERSTYPE1 AS J1
ON J1.PLAYERID = P1.PLAYERID
INNER JOIN SCORETYPE1 AS S1
ON S1.SCOREID = J1.SCOREID
UNION ALL
SELECT P2.PLAYERID, S2.SCORENAME, J2.VALUE
FROM PLAYERS AS P2
INNER JOIN SCOREFORPLAYERSTYPE2 AS J2
ON J1.PLAYERID = P1.PLAYERID
INNER JOIN SCORETYPE2 AS S2
ON S1.SCOREID = J1.SCOREID
SELECT p.playerid
,p.playertype
,IFNULL(sfp1.value, sfp2.value) AS value
,IFNULL(st1.scorename, st2.scorename) AS scorename
FROM players p
LEFT JOIN scoreforplayerstype1 sfp1 ON p.playerid = sfp1.playerid
LEFT JOIN scoreforplayerstype2 sfp2 ON p.playerid = sfp1.playerid
LEFT JOIN scoretype1 st1 ON sfp1.scoreid = st1.scoreid
LEFT JOIN scoretype2 st2 ON sfp2.scoreid = st2.scoreid
That should do it, but as the comments suggest, you should rethink your table structure.