Conditional JOIN between tables? - sql

I have two table and I should write a select query which join this two table but I do not know what is conditional join between this two tables?
Can some body say what is?
TABLE ParameterRegistration
(
RegistrationTime DATETIME,
PatiNo VARCHAR(12),
Source VARCHAR(64),
Code VARCHAR(64),
NameOfCodingSystem VARCHAR(64) NULL,
Name VARCHAR(64),
ValueType CHAR(2) NULL,
NumericValue INT NULL,
StringValue VARCHAR(64) NULL,
TextValue TEXT NULL,
Unit VARCHAR(64) NULL,
UnitCode VARCHAR(64) NULL,
UnitCodingSystem VARCHAR(64) NULL,
Remark VARCHAR(255) NULL,
CreateDate DATETIME,
CreateUserId T_USER_ID
)
and
TABLE External
(
ModDate DATETIME,
ModUserId VARCHAR(12),
UbMem VARCHAR(64),
Code VARCHAR(64),
Name VARCHAR(64),
Service VARCHAR(64),
NameOfCodingSystem VARCHAR(64) NULL,
)

You can only properly join those two tables if they have a relation of some kind.
Check THIS ARTICLE for some info.
Assuming that in your case, the tables are related with the columns Code, NameOfCodingSystem and Name you can make a join like this:
select p.*, e.* from ParameterRegistration p
inner join External e on p.Code = e.Code and
p.NameOfCodingSystem = e.NameOfCodingSystem and
p.Name = e.Name

When joining tables you have to join on fields that are related. Since you did not provide a lot of information it looks like you have 3 fields that possibly could be joined on.
NameOfCodingSystem VARCHAR(64)
Name VARCHAR(64)
Code VARCHAR(64)
So you could technically write your query one of these ways:
SELECT *
FROM ParameterRegistration P
INNER JOIN External E -- or LEFT JOIN, etc
ON P.NameOfCodingSystem = E.NameOfCodingSystem
OR
SELECT *
FROM ParameterRegistration P
INNER JOIN External E -- or LEFT JOIN, etc
ON P.Name = E.Name
OR
SELECT *
FROM ParameterRegistration P
INNER JOIN External E -- or LEFT JOIN, etc
ON P.Code = E.Code
OR you can join on all of the fields at the same time
SELECT *
FROM ParameterRegistration P
INNER JOIN External E -- or LEFT JOIN, etc
ON P.NameOfCodingSystem = E.NameOfCodingSystem AND
P.Name = E.Name AND
P.Code = E.Code
My suggestion would be to study up on JOINs. Here are some resources but there are plenty on the internet:
A Visual Explanation of Joins
SQL Joins
Joins

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 do I prevent duplicate table names when using cross join?

I have the following tables in a SQL database:
t_customers
ID_operator int primary key auto_incr
firstname varchar(30)
lastname varchar(30)
email varchar(100)
t_operator
ID_operator int primary key auto_incr
firstname varchar(30)
lastname varchar(30)
course varchar(10)
I have another table, which represents an order, in which I join both fields when querying another field:
SELECT
*, // table t_orders
t_customers.firstname,
t_customers.lastname,
t_operator.firstname AS operator_firstname,
t_operator.lastname AS operator_lastname
FROM
t_orders
CROSS JOIN
t_customers, t_operator
WHERE
id_orders IS 1;
I have tried to alleviate this by using the AS keyword and the new fields do get added, but I still have 2 fields named "firstname" and "lastname" in my query, preventing me from working with it correctly. Is there any solution besides renaming the tables?
Are you trying to do something like this?
SELECT o.*, // table t_orders
c.firstname, c.lastname,
op.firstname AS operator_firstname,
op.lastname AS operator_lastname
FROM t_orders o JOIN
t_customers c
ON o.id_customer = c.id_customer JOIN
t_operator op
ON c.id_operator = c.id_operator
WHERE id_orders = 1;

Postgresql select count with join

I have two tables:
CREATE TABLE stores (
stores_id varchar PRIMARY KEY,
owner_id varchar
);
CREATE TABLE sets (
sets_id varchar PRIMARY KEY,
stores_id varchar not null,
owner_id varchar not null,
item_id varchar not null,
);
How do I make a request that shows the number of items on the sets in stores?
With selection by owner.
For example:
select
stores.*,
count(sets.item_id)
from stores
LEFT OUTER JOIN sets on stores.owner_id = sets.owner_id
where
stores.owner_id = 'e185775fc4f5'
GROUP BY stores.owner_id;
Thank you.
I think you'd need to join on both the store and the owner, then COUNT(DISTINCT item_id)
select
st.owner_id,
st.stores_id,
count(distinct se.item_id)
from stores st left join
sets se
on st.owner_id = se.owner_id
and st.stores_id = se.stores_id
group by st.owner_id, st.stores_id;
That will give a table that shows the owner, the store, then the number of items
Is this what you want?
select st.stores_id, count(se.item_id)
from stores st left join
sets se
on st.owner_id = se.owner_id
where st.owner_id = 'e185775fc4f5'
group by st.stores_id;

Does Join Order matter performance

create table Employee(
id int identity(1,1) primary key,
Username varchar(50),
FirstName varchar(50),
LastName varchar(50),
DepartID int
)
create table Departments(
id int identity(1,1) primary key,
DepartmentName varchar(50)
)
Both Join result set is same we get Employee matching and non matching.
Select * from Employee E
Left Join
Departments D
ON D.ID= E.DepartID
Select * from Departments D
Right Join Employee E
ON E.DepartID =D.ID
Both of your query are indeed completely interchangeable. And should be no difference in performance nor result.
Most people only use LEFT JOIN since it seems more intuitive, and it's universal syntax - I don't think all RDBMS support RIGHT JOIN. Not all RDBMSs support SQL. For example, SQLite 3 doesn't implement RIGHT and FULL OUTER JOIN.

Using advance SELECT statement for SQL QUERY

I'm trying to use sql query to show name_id and name attribute for all the people who have only grown tomato (veg_grown) and the result are show ascending order of name attribute.
CREATE TABLE people
(
name_id# CHAR(4) PRIMARY KEY,
name VARCHAR2(20) NOT NULL,
address VARCHAR2(80) NOT NULL,
tel_no CHAR(11) NOT NULL
)
CREATE TABLE area
(
area_id# CHAR(5) PRIMARY KEY,
name_id# REFRENCES people,
area_location_adress VARCHAR2(80) NOT NULL
)
CREATE TABLE area_use
(
area_id# REFERENCES area,
veg_grown VARCHAR (20) NOT NULL
)
but the veg_grown attribute has no relation to the people table but the people and area_use table are linked through area table so I tried using INNER JOIN like this which I confused my-self and didn't even work:
SELECT
name, name_id
FROM
people
INNER JOIN
area USING (name_id)
SELECT area_id
FROM area
INNER JOIN area_use USING (area_id)
WHERE veg_grown = 'tomato'
ORDER BY name ASC;
Surely there must be a way to select name_id and name who has only grown tomato in SQL query
I will take any help or advice :) thanks
SELECT p.name, p.name_id
FROM people p
JOIN area a
ON p.name_id = a.name_id
JOIN area_use au
ON a.area_id = au.area_id
AND au.veg_grown = 'tomato'
LEFT JOIN area_use au2
ON a.area_id = au2.area_id
AND au2.veg_grown <> 'tomato'
WHERE au2.area_id IS NULL;
This will use a LEFT JOIN to find people that only grow tomatoes. To find people that grow tomatoes and possibly anything else too, remove the LEFT JOIN part and everything below it.
An SQLfiddle to test with.
EDIT: If your field names contain # in the actual table, you'll need to quote the identifiers and add the #, I left them out in this sample.
AFAICT you only want entries where all info is available, so there are no left/right joins.
SELECT p.name_id, p.name
FROM people p
JOIN area a
ON p.name_id = a.name_id
JOIN area_use au
ON a.area_id = au.area_id
WHERE au.veg_grown = 'tomato'
ORDER BY p.name ASC
I'm not 100% sure of your data model, but this seems to be what you're trying to do.
SELECT name, people.name_id
FROM people, area, area_use
WHERE area.area_id = area_use.area_id
AND veg_grown = 'tomato'
AND area.name_id = people.name_id
ORDER BY name ASC;