Sqlite SQL Statement Not Working As I Expecting - sql

Im using sqlite3 database and i try to get data from two table with cross join.
They have some foreign keys and i can`t get reference value
for currency names (b_currency and s_currency).
They need to be like 'USD','EUR','TRL' etc.
SQL STATEMENT:
select
a.pid,
person.fullname,
a.amount as b_amount,
b.amount as s_amount,
a.currency as b_currency,
b.currency as s_currency,
a.rate as b_rate,
b.rate as s_rate,
`user`.username,
a.`date`
from buy_process as a
inner join person
on a.fullname=person.id
inner join currency
on b_currency=currency.id and s_currency=currency.id
inner join `user`
on a.`user`=`user`.id
cross join sell_process as b
where a.pid=b.pid;
BUY_PROCESS AND SELL_PROCESS TABLE FIELDS ARE SAME:
-- Describe BUY_PROCESS
CREATE TABLE `buy_process`(
id integer primary key AUTOINCREMENT,
pid VARCHAR(50) NOT NULL UNIQUE,
fullname INTEGER NOT NULL,
amount VARCHAR(50) NOT NULL,
currency INTEGER NOT NULL,
rate VARCHAR(50) NOT NULL,
`user` INTEGER NOT NULL,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fkbuy_fullname FOREIGN KEY(fullname) REFERENCES person(id),
CONSTRAINT fkbuy_currency FOREIGN KEY(currency) REFERENCES currency(id),
CONSTRAINT fkbuy_user FOREIGN KEY(`user`) REFERENCES `user`(id)
);
RESULT:
Result image
I tried to change field names but i did not succeed:
a.pid,
person.fullname,
a.amount as b_amount,
b.amount,
currency.name as b_currency,
currency.name as s_currency,
a.rate as b_rate,
b.rate as s_rate,
`user`.username,
a.`date`
from buy_process as a
inner join person
on a.fullname=person.id
inner join currency
on b_currency=currency.id and s_currency=currency.id
inner join `user`
on a.`user`=`user`.id
cross join sell_process as b
where a.pid=b.pid;

I don't understand what you want to achieve with the cross join (you have a condition a.pid=b.pid, why not just inner join them?).
You need to join the currency table twice, once for the buy currency, and once for the sell currency:
select
...
b_cncy.name as b_currency,
s_cncy.name as s_currency,
...
from
buy_process as bp
inner join
sell_process as sp
on bp.pid=sp.pid
inner join
currency b_cncy
on b_cncy.id=bp.currency
inner join currency s_cncy
on s_cncy.id=sp.currency
inner join `user` usr
on usr.id=bp.`user`

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

Query to display student_no, prj_name and prj_dur

I have following table
TBL_STUDENT (STUDENT_NO VARCHAR2(3) PRIMARY KEY STUDENT_NAME VARCHAR2 (10) STUDENT_DOB DATE STUDENT_DOJ DATE)
TBL_PROJECT (PRJ_NO VARCHAR2 (3) PRIMARY KEY PRJ_NAME VARCHAR2 (15) PRJ_DUR NUMBER (2) PRJ_PLATFORM VARCHAR2 (10))
TBL_STUDENTPROJECT (STUDENT_NO VARCHAR2 (3) PRJ_NO VARCHAR2 (3) DESIGNATION VARCHAR2 (10) PRIMARYKEY (STUDENT_NO,PRJ_NO,DESIGNATION) FOREIGN KEY(STUDENT_NO) of TBL_STUDENT FOREIGN KEY(PRJ_NO) of TBL_PROJECT)
I want to display student_no, prj_name and prj_dur;
select p.prj_name, s.student_no, p.prj_dur from tbl_project p inner join on tbl_studentproject s where p.prj_no = s.prj_no
You need to do Inner join to find prj_name, student_no and prj_dur.
SELECT p.PRJ_NAME, s.STUDENT_NO, p.PRJ_DUR
from TBL_STUDENTPROJECT sp
INNER JOIN TBL_STUDENT s on sp.STUDENT_NO = s.STUDENT_NO
INNER JOIN TBL_PROJECT p ON sp.PRJ_NO = p.PRJ_NO;
If you need to have all the project and project duration of each student then use left join.
SELECT p.PRJ_NAME, s.STUDENT_NO, p.PRJ_DUR
FROM TBL_STUDENT s
LEFT JOIN TBL_STUDENTPROJECT sp on sp.STUDENT_NO=s.STUDENT_NO
LEFT JOIN TBL_PROJECT p ON sp.PRJ_NO=p.PRJ_NO;

How to compose select request using many-to-many relationship in PostgreSQL?

I have this tables:
CREATE TABLE orders (
order_id serial PRIMARY KEY
, number_of_things int
);
CREATE TABLE things (
thing_id serial PRIMARY KEY
, cost int
);
CREATE TABLE orders_to_things (
order_id int REFERENCES orders (order_id)
, thing_id int REFERENCES things (thing_id)
);
How to compose a request for select all orders where cost of things more than some number?
I tried to use:
SELECT orders.order_id
FROM orders
INNER JOIN orders_to_things ON (orders_to_things.order_id = orders.order_id)
JOIN things ON (orders_to_things.thing_id=things.thing_id)
WHERE (select SUM(things.cost) FROM things) > *some number*
but didn't get the correct result.
Try this:
SELECT O.order_id, sum(T.cost)
FROM orders O
INNER JOIN orders_to_things ON orders_to_things.order_id = orders.order_id
JOIN things T ON orders_to_things.thing_id=things.thing_id
GROUP BY O.order_id
HAVING T.cost > 'number....'
If you want all order ids, you don't need the orders table. The simplest way to write the query is:
SELECT ott.order_id, sum(t.cost)
FROM orders_to_things ott JOIN
things t
ON ott.thing_id = t.thing_id
GROUP BY ott.order_id
HAVING sum(t.cost) > <number>;

How to select NOT using SQL JOIN

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

How can I get a count from a table joined to a Left Outer Join?

I have three tables. A table of tests (AdminTest), a table of tests that belong to a user (UserTest) and a table of questions that belongs to each of the user tests (UserTestQuestion):
AdminTest
CREATE TABLE [dbo].[AdminTest] (
[AdminTestId] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (100) NOT NULL
CONSTRAINT [PK_AdminTest] PRIMARY KEY CLUSTERED ([AdminTestId] ASC));
UserTest
CREATE TABLE [dbo].[UserTest] (
[UserTestId] INT IDENTITY (1, 1) NOT NULL,
[AdminTestId] INT NOT NULL,
[UserId] INT NOT NULL
CONSTRAINT [PK_UT] PRIMARY KEY CLUSTERED ([UserTestId] ASC));
UserTestQuestion
CREATE TABLE [dbo].[UserTestQuestion] (
[UserTestQuestionId] INT IDENTITY (1, 1) NOT NULL,
[UserTestId] INT NOT NULL,
[Answered] BIT DEFAULT ((0)) NOT NULL
CONSTRAINT [PK_UQ] PRIMARY KEY CLUSTERED ([UserTestQuestionId] ASC)
);
An AdminTest may or may not have a UserTest
A UserTest will always have UserTestQuestions
I created this SQL to get data from AdminTest and UserTest:
SELECT userTest.StartedDate,
temp.AdminTestId
-- AnsweredCount
-- I want to get a count of the number of rows
-- from the table UserTestQuestions that have
-- the column 'Answered' set to 1 here.
FROM
( SELECT AdminTest.AdminTestId
FROM AdminTest
JOIN AdminTestQuestion ON AdminTest.AdminTestId = AdminTestQuestion.AdminTestId
GROUP BY
AdminTest.AdminTestId
) temp
LEFT OUTER JOIN UserTest ON temp.AdminTestId = UserTest.AdminTestId
-- I want the above join to only join those UserTest tables that
-- have a value of UserId set to for example 25
But now I am stuck and there are two things I need help with.
I need to be able to show only the UserTests that belong to a given UserId
I need to report a count of the rows in the UserTests that have Answered set to 1.
Can someone give me advice on how to add this functionality to my SQL?
Here's an example of what I need:
AdminTestId UserTestStartedData AnsweredCount
1 1/1/2001 25
2 2/2/2002 10
3
4 4/4/2004 10
Join the UserTestQuestion table and use Conditional Aggregate to count only when answered = 1
SELECT userTest.StartedDate,
temp.AdminTestId,
Count(CASE
WHEN UT.answered = 1 THEN 1
END) cnt
FROM (SELECT AdminTest.AdminTestId
FROM AdminTest
JOIN AdminTestQuestion
ON AdminTest.AdminTestId = AdminTestQuestion.AdminTestId
GROUP BY AdminTest.AdminTestId) temp
INNER JOIN UserTest
ON temp.AdminTestId = UserTest.AdminTestId
INNER JOIN [UserTestQuestion] UT
ON UserTest.UserTestId = UT.UserTest
Where UserTest.UserTestId = 25
Also If you want join to only join those UserTest tables that
have a value of UserId=25 then left join will be converted to Inner join
Update :
SELECT A.StartedDate,
temp.AdminTestId,
Count(CASE
WHEN A.answered = 1 THEN 1
END) cnt
FROM (SELECT AdminTest.AdminTestId
FROM AdminTest
JOIN AdminTestQuestion
ON AdminTest.AdminTestId = AdminTestQuestion.AdminTestId
GROUP BY AdminTest.AdminTestId) temp
LEFT OUTER JOIN (SELECT userTest.StartedDate,
UT.answered,
UserTest.AdminTestId
FROM UserTest
INNER JOIN [UserTestQuestion] UT
ON UserTest.UserTestId = UT.UserTest
WHERE UserTest.UserTestId = 25) A
ON temp.AdminTestId = A.AdminTestId
Group by A.StartedDate,temp.AdminTestId