SQL Database SELECT JOIN Query - sql

I can do this question with three tables. However, the extra table confuses me a lot. Here is the schema:
COURSE(CourseID, CourseName)
COURSEMODULES(CourseID, ModuleID)
MODULE (ModuleID, ModuleName, LecturerID)
LECTURER(LecturerID, FirstName, Surname, Email)
How would you ensure that more than one lecturer can teach on a module?

I've made some assumptions about the data types contained in your schema. The following query will allow you to select only lecturers that are teaching more than 1 module:
SELECT
COUNT(ModuleName) AS number_of_modules_taught
, FirstName
, Surname
, Email
, CourseName
FROM
(SELECT
l.FirstName
, l.Surname
, l.Email
, c.CourseName
, m.ModuleName
FROM course c
JOIN coursemodules cm ON c.CourseID = cm.CourseID
JOIN module m ON cm.ModuleID = m.ModuleID
JOIN lecturer l ON m.LecturerID = l.lecturerID
) AS modules_by_lecturer
GROUP BY 2, 3, 4, 5
HAVING COUNT(ModuleName) > 1
I've also made this available on SQL Fiddle for you to play around with: http://sqlfiddle.com/#!9/9f25d5/4
Edit: After the fact it occurred to me that you might actually care about loading the data into tables such that one lecturer can be mapped to more than one module. This is accomplished by allowing the ModuleID field to be unique, and mapping it to the same lecturer:
CREATE TABLE course (CourseID VARCHAR(20), CourseName VARCHAR(100));
CREATE TABLE coursemodules (CourseID VARCHAR(20), ModuleID VARCHAR(20));
CREATE TABLE module (ModuleID VARCHAR(20), ModuleName VARCHAR(100), LecturerID VARCHAR(20));
CREATE TABLE lecturer (LecturerID VARCHAR(20), FirstName VARCHAR(50), Surname VARCHAR(50), Email VARCHAR(100));
INSERT INTO course (CourseID, CourseName) VALUES(12345, 'Pysics 101'),(23456, 'English 102'),(34567, 'Computer Science 306');
INSERT INTO coursemodules (CourseID, ModuleID) VALUES(12345, 13579),(12345, 79135),(23456, 35791),(34567, 57913);
INSERT INTO module (ModuleID, ModuleName, LecturerID) VALUES(13579, 'Newton\'s Laws', 24680),(79135, 'Thermodynamics', 24680),(35791, 'Chaucer', 46802),(57913, 'Lambda Functions in Java', 68024);
INSERT INTO lecturer (LecturerID, FirstName, Surname, Email) VALUES(24680, 'Stephen', 'Hawking', 'shawking#cambridge.com'), (80246, 'Neil', 'Tyson', 'ndtyson#amnh.org'),(46802, 'George', 'Martin', 'grrmartin#westeros.com'),(68024, 'Linus', 'Torvalds', 'lt#linux.org');

Related

Learning SQL, trying to find out why my FK isn't working

These are my tables:
CREATE TABLE Engineers
(
EID INT PRIMARY KEY,
Lastname varchar(40),
Firstname varchar(25),
Email varchar(60),
Graddate varchar(10)
);
CREATE TABLE Faculty
(
FID INT PRIMARY KEY,
Lastname varchar(40),
Firstname varchar(25),
Email varchar(60),
Hiredate varchar(10)
);
CREATE TABLE Classes
(
CID INT PRIMARY KEY,
Subject varchar(12),
Catalognbr INT,
Title varchar(40)
);
CREATE TABLE ClassEnrollments
(
EnID INT PRIMARY KEY,
EngineerID INT,
FOREIGN KEY(EngineerID) REFERENCES Engineers(EID),
FacultyID INT,
FOREIGN KEY(FacultyID) REFERENCES Faculty(FID),
ClassID INT,
FOREIGN KEY(ClassID) REFERENCES Classes(CID)
);
Here is one snip of the data I'm inserting:
INSERT INTO Engineers(EID, Lastname, Firstname, Email, Graddate)
VALUES(1, 'Bloober', 'Martha', 'BlooberBoogers#gmail.com', '10/29/2022');
INSERT INTO Faculty(FID, Lastname, Firstname, Email, Hiredate)
Values(1, 'Hickory', 'Bob', 'IamMrClean#gmail.com', '10/30/1995');
INSERT INTO Classes(CID, Subject, Catalognbr, Title)
Values(1, 'SDEV', '350', 'Database Security');
INSERT INTO ClassEnrollments(EnID, EngineerID, FacultyID, ClassID)
Values(1, 1, 1, 1);
Now everything runs through but my insert into classenrollments isn't working, I'm assuming I am inserting my foreign keys wrong. But am unsure, I have been looking a bit online but haven't seen anything that I have done so far. Any suggestions would be great.
Here is my error message:
Error starting at line : 84 in command -
INSERT INTO ClassEnrollments(EnID, EID, FID, CID)
Values(1, 1, 1, 1)
Error at Command Line : 84 Column : 46
Error report -
SQL Error: ORA-00904: "CID": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
Use the correct column names
INSERT INTO ClassEnrollments(EnID, EngineerID, FacultyID, ClassID)
Values(1, 1, 1, 1);
What you want according to your comments is:
SELECT e.Firstname AS engineerFirstname, e.Lastname as engineerLastname,
f.Firstname AS facultyFirstname, f.Lastname as facultyLastname,
c.Title AS ClassTitle
From ClassEnrollments ce
INNER JOIN Engineers e ON e.EID = ce.EngineerID
INNER JOIN Faculty f ON f.FID = ce.FacultyID
INNER JOIN Classes c ON c.CID = ce.ClassID

MS SQL Stored procedure to get the value

I have 3 tables
Staff table:
EmpId CandidateId
------------------------
1 2
Candidate table:
CandidateId Firstname Last name CountryId PassportCountry
--------------------------------------------------------------------
1 Mark Antony 2 3
2 Joy terry 1 3
Country:
CountryId Name
---------------------------
1 USA
2 UK
3 Australia
User will pass the EmpId in the querystring I need to show the candidate details according to the empId. I have only one country table and using that table for country, passportport country. So I need to get the country name when I get the candidate value.
How to write the stored procedure to get the candidate details. Im not good in sql. Can you guys help me on this. Thanks in advance.
Hi I tried the below script to get the country name and passport country name. I can get the country name, but not the passport country.
SELECT
FirstName,
LastName,
PassportCountry,
Country.CountryName as Country
from Candidate
inner join Country
on country.CountryId=candidate.country
where CandidateId=#CandidateId;
This should get you going in the right direction.
Basically, since you're referencing the Country table twice, you need to join it twice.
declare #staff table (EmpId int, CandidateId int)
insert into #staff values (1, 2 )
declare #Candidate table (CandidateId int, Firstname nvarchar(50), Lastname nvarchar(50), CountryId int, PassportCountry int)
insert into #Candidate
values (1, 'Mark', 'Antony', 2, 3),
(2, 'Joy', 'Terry', 1, 3)
declare #Country table (CountryId int, Name nvarchar(50))
insert into #Country
values (1, 'USA'),
(2, 'UK'),
(3, 'Australia')
declare #empID int
set #empID = 1
SELECT
FirstName,
LastName,
t2.Name as PersonCountry,
t3.Name as PassportCountry
from #staff s
inner join #Candidate t1 on s.CandidateId = t1.CandidateId
inner join #Country t2 on t1.CountryId=t2.CountryId
inner join #Country t3 on t1.PassportCountry=t3.CountryId
where s.EmpId=#empID;

Split One table into Two in SQL Server 2008

I need to break one table (structure built by someone else but I need the data it contains thousands of records) into two new tables I created.
Table Name: Customers_Info (Old Table)
FullName Telephone Address
Adam Johnson 01555777 Michigan
John Smith 01222333 New York
John Smith 01222333 New Jersey
Lara Thomas 01888999 New Mexico
The above is the old table. Now I created two tables to hold the data, one table for customers with a default address, and the other table to hold additional addresses. In the shown example I need 3 persons to be listed in the Customers table, and the address of "John Smith" (the second one New Jersey) to be listed in the Addresses table.
The common field to look at here is "Telephone" and it's unique for every customer.
Here's how the result should be display.
Table Name: Customers (New Table)
CustomerID FullName Telephone Default_Address
1 Adam Johnson 01555777 Michigan
2 John Smith 01222333 New York
3 Lara Thomas 01888999 New Mexico
Table Name: Addresses (New Table)
AddressID CustomerID Address
1 2 New Jersey
Of course it was easy to copy all data into the new Customers table, but what I'm stuck at now, is how to remove the duplicates from Customers and insert them into the Addresses table with the Customer ID and Address only.
Thanks!
Give a try with below code and let me know the comments/results.
CREATE TABLE [Customers_Info]
(
FullName VARCHAR(50)
,Telephone VARCHAR(50)
,Address VARCHAR(50)
)
GO
CREATE TABLE Customers
(
CustomerID INT IDENTITY(1,1)
,FullName VARCHAR(50)
,Telephone VARCHAR(50)
,Default_Address VARCHAR(50)
)
GO
ALTER TABLE dbo.Customers ADD CONSTRAINT PK_Customers
PRIMARY KEY CLUSTERED (CustomerID);
GO
CREATE TABLE Addresses
(
AddressID INT IDENTITY(1,1)
,CustomerID INT
,[Address] VARCHAR(50)
)
GO
ALTER TABLE dbo.Addresses ADD CONSTRAINT PK_Addresses
PRIMARY KEY CLUSTERED (AddressID);
GO
ALTER TABLE Addresses ADD CONSTRAINT FK_CustomerID_Addresses_Customers FOREIGN KEY (CustomerID)
REFERENCES dbo.Customers(CustomerID);
GO
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777', 'Michigan')
INSERT INTO [Customers_Info] VALUES ('John Smith' , '01222333', 'New York')
INSERT INTO [Customers_Info] VALUES ('John Smith' , '01222333', 'New Jersey')
INSERT INTO [Customers_Info] VALUES ('Lara Thomas' , '01888999', 'New Mexico')
INSERT INTO [Customers_Info] VALUES ('Lara Thomas' , '01888999', 'New Mexico1')
INSERT INTO [Customers_Info] VALUES ('Lara Thomas' , '01888999', 'New Mexico2')
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777', 'Michigan1')
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777A', 'Michigan')
INSERT INTO [Customers_Info] VALUES ('Adam Johnson', '01555777A', 'Michigan2')
GO
SELECT * FROM [Customers_Info]
--DELETE FROM Customers
--TRUNCATE TABLE Addresses
------------------------------------------------------------------------------------------------------------------
;WITH a as
(
SELECT FullName,Telephone,[Address],
rn = row_number() over (partition by FullName, Telephone order by FullName)
FROM [Customers_Info]
)
INSERT INTO Customers SELECT
FullName,Telephone,[Address] from a where rn = 1
------------------------------------------------------------------------------------------------------------------
;WITH b as
(
SELECT FullName,Telephone,[Address],
rn = row_number() over (partition by FullName, Telephone order by FullName)
FROM [Customers_Info]
)
INSERT INTO Addresses SELECT CI.CustomerID,b.[Address] FROM Customers CI
INNER JOIN b ON b.FullName=CI.FullName AND b.Telephone=CI.Telephone
WHERE b.rn>1
SELECT * FROM Customers
SELECT * FROM Addresses
DROP TABLE [Customers_Info]
GO
DROP TABLE Addresses
GO
DROP TABLE Customers
GO
It would be more normalized if you broke it up into one more table for three total tables. Have the Customers table that has only customer data, have the Address table (which you could possibly rename to State) that has only the Address, then a CustomerAddress table that has both keys to each of those tables as Foreign Keys.
I will start you off to begin:
INSERT INTO Customers (FullName, Telephone)
SELECT DISTINCT FullName, Telephone
FROM Customers_Info
You would do the same for Address. For the 3rd table, you would perform the lookups like this:
INSERT INTO CustomerAddress (CustomerID, AddressID)
SELECT C.CustomerID, A.AddressID
FROM Customers_Info CI
INNER JOIN Customers C
ON CI.Telephone = C.Telephone
INNER JOIN Address A
ON CI.Address = A.Address

Join on select SQL Server stored procedure

I am trying to create a stored procedure to insert data into 2 tables in SQL Server.
I have tried putting the join in all different positions of the code and still get an error.
CREATE PROCEDURE sp_Insert_Person
#s_FirstName nvarchar(50),
#s_Surname nvarchar(50),
#s_AddressLine1 nvarchar(50),
#s_AddressLine2 nvarchar(50),
#s_Postcode nvarchar(10),
#s_Phone nvarchar(50),
#s_Department nvarchar(50)
AS
BEGIN
INSERT INTO
tbl_person(FirstName, Surname, AddressLine1, AddressLine2,
Postcode, Phone, tbl_Department.Department)
INNER JOIN tbl_person
ON tbl_person.DepartmentID = tbl_Department.DepartmentID
VALUES (#s_FirstName,
#s_Surname,
#s_AddressLine1,
#s_AddressLine2,
#s_Postcode,
#s_Phone,
#s_Department)
END
I have tried the join at the end and at the beginning I have looked all over for insert joins, wondered if i was just getting it all wrong.
I have a department table and a person table and thought I would be able to access the department table through the FK DepartmentID which I have in the Person table, as is the PK in the Department table
I think something like this
INSERT INTO tbl_person
(FirstName,
Surname,
AddressLine1,
AddressLine2,
Postcode,
Phone,
DepartmentID)
Select #s_FirstName,
#s_Surname,
#s_AddressLine1,
#s_AddressLine2,
#s_Postcode,
#s_Phone,
tbl_Department.DepartmentID
from tbl_person
join DepartmentID
ON tbl_person.DepartmentID = tbl_Department.DepartmentID
where tbl_Department.Department = #s_Department
CREATE PROCEDURE sp_Insert_Person
#s_FirstName nvarchar(50),
#s_Surname nvarchar(50),
#s_AddressLine1 nvarchar(50),
#s_AddressLine2 nvarchar(50),
#s_Postcode nvarchar(10),
#s_Phone nvarchar(50),
#s_Department nvarchar(50)
AS
BEGIN
if not Exists(select * from tbl_Department where Department=#s_Department)
insert into tbl_Department (Department) Values (#s_Department)
INSERT INTO tbl_person
(FirstName,
Surname,
AddressLine1,
AddressLine2,
Postcode,
Phone,
DepartmentID)
select #s_FirstName,
#s_Surname,
#s_AddressLine1,
#s_AddressLine2,
#s_Postcode,
#s_Phone,
#s_Department,
DepartmentID
from tbl_Department
where Department=#s_Department
END

Moving away from STI - SQL to break single table into new multi-table structure

I am moving old project that used single table inheritance in to a new database, which is more structured. How would I write a SQL script to port this?
Old structure
I've simplified the SQL for legibility.
CREATE TABLE customers (
id int(11),
...
firstName varchar(50),
surname varchar(50),
address1 varchar(50),
address2 varchar(50),
town varchar(50),
county varchar(50),
postcode varchar(50),
country varchar(50),
delAddress1 varchar(50),
delAddress2 varchar(50),
delTown varchar(50),
delCounty varchar(50),
delPostcode varchar(50),
delCountry varchar(50),
tel varchar(50),
mobile varchar(50),
workTel varchar(50),
);
New structure
CREATE TABLE users (
id int(11),
firstName varchar(50),
surname varchar(50),
...
);
CREATE TABLE addresses (
id int(11),
ForeignKey(user),
street1 varchar(50),
street2 varchar(50),
town varchar(50),
county varchar(50),
postcode varchar(50),
country varchar(50),
type ...,
);
CREATE TABLE phone_numbers (
id int(11),
ForeignKey(user),
number varchar(50),
type ...,
);
With appropriate cross-database notations for table references if appropriate:
INSERT INTO Users(id, firstname, surname, ...)
SELECT id, firstname, surname, ...
FROM Customers;
INSERT INTO Addresses(id, street1, street2, ...)
SELECT id, street1, street2, ...
FROM Customers;
INSERT INTO Phone_Numbers(id, number, type, ...)
SELECT id, phone, type, ...
FROM Customers;
If you want both the new and the old address (del* version), then repeat the address operation on the two sets of source columns with appropriate tagging. Similarly, for the three phone numbers, repeat the phone number operation. Or use a UNION in each case.
First make sure to backup your existing data!
The process is differnt if you are going to use the original id field or generate a new one.
Assuming you are going to use the orginal, make sure that you have the ability to insert id fields into the table before you start (the SQL Server equivalent if you are autogenrating the number is Set identity Insert on, not sure what mysql would use). Wirte an insert from the old table to the parent table:
insert newparenttable (idfield, field1, field2)
select idfield, field1, field2 from old parent table
then write similar inserts for all the child tables depending on what fields you need. Where you have multiple phone numbers in differnt fields, for instance, you would use a union all stament as your insert select.
Insert newphone (phonenumber, userid, phonetype)
select home_phone, id, 100 from oldparenttable
union all
select work_phone, id, 101 from oldparenttable
Union all
select cell_phone, id, 102 from oldparenttable
If you are going to have a new id generated, then create the table with a field for the old id. You can drop this at the end (although I'd keep it for about six months). Then you can join from the new parent table to the old parent table on the oldid and grab the new id from the new parent table when you do you inserts to child tables. Something like:
Insert newphone (phonenumber, userid, phonetype)
select home_phone, n.id, 100 from oldparenttable o
join newparenttable n on n.oldid = o.id
union all
select work_phone, n.id, 101 fromoldparenttable o
join newparenttable n on n.oldid = o.id
Union all
select cell_phone, n.id, 102 from oldparenttable o
join newparenttable n on n.oldid = o.id