You are on page 1of 57

/*

******************** Targeted Technology Institute


**********************************

Welcome to Targeted Technology Institute's Practical SQL Server Database


Development Training

Level: From Basic to Advanced

Here we build and use a database for a hypothetical Health Record Management
System, HRMS

TABLES : Patient, Doctor, Disease and Diagnosis, Medicine, PharmacyPersonel,


Prescription, MedicinePrescribed,Nurse, Department,Room,Prescribes ...
---> you may be required to add more tables

- Please understnad the design the tables and thier relationships


- If at any point you couldn't insert the given data nor encountered a
problem - try to figure out what caused it.
- As instructed under each insert statement, pls insert some more data into
the tables

*/
USE master;
GO

DROP DATABASE IF EXISTS HRMSDB;


GO

CREATE DATABASE HRMSDB;


GO

USE HRMSDB;
GO

-- Creating tables with applicable constraints

CREATE TABLE Patient


(
mrn CHAR(5) NOT NULL,
pFName VARCHAR(30) NOT NULL,
pLName VARCHAR(30) NOT NULL,
PDoB DATE NOT NULL,
insuranceId CHAR(7) NULL,
gender CHAR(1) NOT NULL,
SSN CHAR(11) NULL,
stAddress VARCHAR(25) NOT NULL,
city VARCHAR(25) NOT NULL,
[state] CHAR(2) NOT NULL,
zipCode CHAR(5) NOT NULL,
registeredDate DATE NOT NULL DEFAULT GETDATE(),
CONSTRAINT PK_Patient_mrn PRIMARY KEY (mrn),
CONSTRAINT CK_Patient_mrn_Format CHECK(mrn LIKE '[A-Z][A-Z][0-9][0-9][0-9]'),
CONSTRAINT UQ_Patient_insuranceId UNIQUE (insuranceId),
CONSTRAINT CK_Patient_gender_Format CHECK(gender IN ('F', 'M', 'U')),
CONSTRAINT CK_Patient_SSN_Format CHECK ((SSN LIKE '[0-9][0-9][0-9][-][0-9][0-
9][-][0-9][0-9][0-9][0-9]') AND (SSN NOT LIKE '000-00-0000')),
CONSTRAINT UQ_Patient_SSN UNIQUE (SSN),
CONSTRAINT CK_Patient_state_Format CHECK([state] LIKE '[A-Z][A-Z]'),
CONSTRAINT CK_Pateint_zipCode_Fomrat CHECK((zipCode LIKE '[0-9][0-9][0-9][0-
9][0-9]') AND (zipCode NOT LIKE '00000'))
);
GO

CREATE TABLE Employee


(
empId CHAR(5) NOT NULL,
empFName VARCHAR(25) NOT NULL,
empLName VARCHAR(25) NOT NULL,
SSN CHAR(11) NOT NULL,
DoB DATE NOT NULL,
gender CHAR(1) NOT NULL,
salary DECIMAL(8,2) NULL,
employedDate DATE NOT NULL,
strAddress VARCHAR (30) NOT NULL,
apt VARCHAR(5) NULL,
city VARCHAR(25) NOT NULL,
[state] CHAR(2) NOT NULL,
zipCode CHAR(5) NOT NULL,
phoneNo CHAR(14) NOT NULL,
email VARCHAR(50) NULL,
empType VARCHAR(20) NOT NULL,
CONSTRAINT PK_Employee_empId PRIMARY KEY (empId)
);
GO

CREATE TABLE Disease


(
dId INT NOT NULL,
dName VARCHAR(100) NOT NULL,
dCategory VARCHAR(50) NOT NULL,
dType VARCHAR(40) NOT NULL,
CONSTRAINT PK_Disease_dId PRIMARY KEY (dId),
);
GO

CREATE TABLE Doctor


(
empId CHAR(5) NOT NULL,
docId CHAR(4) NOT NULL,
licenseNo CHAR(11) UNIQUE NOT NULL,
licenseDate DATE NOT NULL,
[rank] VARCHAR(25) NOT NULL,
specialization VARCHAR(50) NOT NULL,
CONSTRAINT PK_Doctor_docId PRIMARY KEY (docId),
CONSTRAINT FK_Doctor_Employee_empId FOREIGN KEY (empId) REFERENCES Employee
(empId) ON DELETE CASCADE ON UPDATE CASCADE
);
GO
CREATE TABLE Nurse
(
empId CHAR(5) NOT NULL,
nuId CHAR(4) NOT NULL,
licenseNo CHAR(11) NOT NULL,
licenseDate DATE NOT NULL,
[rank] VARCHAR(25) NOT NULL,
specialization VARCHAR(50) NOT NULL,
CONSTRAINT PK_Nurse_nuId PRIMARY KEY (nuId),
CONSTRAINT FK_Nurse_Employee_empId FOREIGN KEY (empId) REFERENCES Employee
(empId) ON DELETE CASCADE ON UPDATE CASCADE
);
GO

CREATE TABLE Department


(
departmentId INT NOT NULL,
departmentName TEXT NOT NULL,
departmentHead INT NOT NULL
CONSTRAINT PK_Department_departmentId PRIMARY KEY (departmentId)
);

CREATE TABLE Room


(
roomNumber INT NOT NULL,
roomType TEXT NOT NULL,
blockFloor INT NOT NULL,
blockCode INT NOT NULL,
CONSTRAINT PK_Room_roomNumber PRIMARY KEY (roomNumber)
);

CREATE TABLE Prescribes


(
physician INT NOT NULL,
patient INT NOT NULL,
medication INT NOT NULL,
appointment INT NOT NULL,
dose TEXT
);

CREATE TABLE Diagnosis


(
diagnosisNo INT NOT NULL,
mrn CHAR(5) NOT NULL,
docId CHAR(4) NULL,
dId INT NOT NULL,
diagDate DATE DEFAULT GETDATE() NOT NULL,
diagResult VARCHAR(1000) NOT NULL,
CONSTRAINT PK_Diagnosis_diagnosisNo PRIMARY KEY (diagnosisNo),
CONSTRAINT FK_Diagnosis_Patient_mrn FOREIGN KEY (mrn) REFERENCES
Patient(mrn),
CONSTRAINT FK_Diagnosis_Doctor_docId FOREIGN KEY (docId) REFERENCES
Doctor(docId) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT FK_Diagnosis_Disease_dId FOREIGN KEY (dId) REFERENCES Disease(dId)
);
GO

CREATE TABLE PharmacyPersonel


(
empId CHAR(5) NOT NULL,
pharmacistLisenceNo CHAR (11) NOT NULL,
licenseDate DATE NOT NULL,
PCATTestResult INT NULL,
[level] VARCHAR (40) NOT NULL,
CONSTRAINT FK_PharmacyPersonel_empId FOREIGN KEY (empId) REFERENCES Employee
(empId),
CONSTRAINT UQ_PharmacyPersonel_pharmacistLisenceNo UNIQUE
(pharmacistLisenceNo)
);
GO

CREATE TABLE Medicine


(
mId SMALLINT NOT NULL,
brandName VARCHAR(40) NOT NULL,
genericName VARCHAR(50) NOT NULL,
qtyInStock INT NOT NULL,
[use] VARCHAR(50) NOT NULL,
expDate DATE NOT NULL,
unitPrice DECIMAL(6,2) NOT NULL,
CONSTRAINT PK_Medicine_mId PRIMARY KEY (mId)
);
GO

CREATE TABLE Prescription


(
prescriptionId INT NOT NULL,
diagnosisNo INT NOT NULL,
prescriptionDate DATE NOT NULL DEFAULT GETDATE(),
CONSTRAINT PK_Prescription_prescriptionId PRIMARY KEY (prescriptionId),
CONSTRAINT FK_Prescription_Diagnosis_diagnosisNo FOREIGN KEY (diagnosisNo)
REFERENCES Diagnosis(diagnosisNo)
);
GO

CREATE TABLE MedicinePrescribed


(
prescriptionId INT NOT NULL,
mId SMALLINT NOT NULL,
dosage VARCHAR(50) NOT NULL,
numberOfAllowedRefills TINYINT NOT NULL,
CONSTRAINT PK_MedicinePrescribed_prescriptionId_mId PRIMARY
KEY(prescriptionId, mId),
CONSTRAINT FK_MedicinePrescribed_prescriptionId FOREIGN KEY (prescriptionId)
REFERENCES Prescription(prescriptionId),
CONSTRAINT FK_MedicinePrescribed_mId FOREIGN KEY (mId) REFERENCES
Medicine(mId)
);
GO

-- Inserting data into tables of HRMS database,

INSERT INTO Disease


VALUES (1, 'Strep throat', 'Bacterial infections', 'Contageous'),
(2, 'Acquired hemophilia','Blood Diseases','Type2'),
(3, 'Accessory pancreas ','Digestive Diseases','xyz'),
(4, 'Cholera ', 'Bacterial infections', 'Contageous'),
(5, 'Acatalasemia ','Blood Diseases', 'Chronic'),
(6, 'Acute fatty liver of pregnancy ','Digestive Diseases','Non
Contageous'),
(7, 'Cholera','Bacterial Disease', 'Acute diarrheal'),
(8, 'Diabetes', 'Gestational diabetes', 'Type 1'),
(9, 'Cancer', 'Sarcoma', 'Anal cancer'),
(10, 'Fever', 'Body temperature', 'Low Grade'),
(11, 'Alzheimer', 'Dimentia', 'Late onset');

-- Insert 5 more diseases


GO

INSERT INTO Medicine


VALUES (1, 'Xaleto','Rivaroxi', 200, 'Anticoagulant', '2022-12-31', 67.99),
(2, 'Eliquis', 'Apiza',500, 'ACE inhitor', '2021-06-06', 23.49),
(3, 'TransAcid', 'Inhibitor', 600, 'Something','2020-12-31', 9.99),
(4, 'Fosamax', 'alendronate tablet', 200, 'treat certain types of
bone loss in adults','2022-12-31',58),
(5, 'Hexalen capsules','altretamine',150,'Ovarian cancer','2020-12-
31',26),
(6, 'Prozac','Fluoxetine', 125, 'Anti-depressent', '2019-12-31',
43.99),
(7, 'Glucofage','Metformine', 223, 'Anti-Diabetic', '2019-10-13',
22.99),
(8, 'Advil', 'Ibuprofine', 500, 'Pain killer', '2023-01-01', 0.10),
(9, 'Amoxy','Amoxilcillin', 2000, 'Antibiotics', '2021-12-31',
0.20 ),
(10, 'Acetominophen', 'Tylenol', 444 , 'Fever', '2022-11-21', 5.00),
(11, 'Ampicillin', 'Principen', 555, 'Infection', '2022-09-11',
56.89),
(12, 'Asprin', 'Acetylsalicylic', 454, 'Pain', '2021-23-12',45.54),
(13, 'Atorvastatin', 'Lipitor', 343, 'Cholesterol', '2022-15-14',
34.56),
(14, 'Ativan', 'Lorazepam', 344, 'Sleep Difficulty', '2022-12-10',
23.34);
SELECT *
FROM Medicine

-- Insert 5 more Medicine


GO

INSERT INTO Patient


VALUES ('PA001', 'Kirubel', 'Wassie', '09-12-1985', 'kki95', 'M','031-
56-3472','2578 kk st', 'Alexandria', 'VA', '22132','2018-01-01'),
('PA002', 'Harsha', 'Sagar', '11-19-1980', 'wes41', 'F','289-01-
6994','3379 bb st', 'Miami', 'FL', '19376','2017-09-02'),
('PA003', 'Fekadu', 'Gonfa', '05-20-1990', 'oi591', 'M','175-50-
1235','1538 ff st', 'Seattle', 'WA', '35800','2018-01-01'),
('PA004', 'Arsema', 'Negera', '01-25-1978', 'iuu53', 'F','531-31-
3308','2928 aa st', 'Silver Spring', 'MD', '51763','2017-02-01'),
('PA005', 'John', 'Craig', '12-31-1965', 'iu979', 'M','231-61-
8422','1166 jj st', 'Alexandria', 'VA', '22132','2019-01-03'),
('PA006', 'Maria', 'Michael', '08-12-1979', 'mk216', 'F', '786-
32-0912','7866 mm st', 'Silver Spring', 'MD', '51763','2018-01-01'),
('PA007', 'Derek', 'Nagaraju', '02-18-1975', 'sd025', 'M','120-
21-6743','8889 ff st', 'Silver Spring', 'MD', '51763','2019-02-20'),
('PA008', 'Birtukan', 'Wale', '01-27-1989', 'is489', 'F','013-32-
6789','5464 bb st', 'Seattle', 'WA', '35800','2018-01-05'),
('PA009', 'Yehualashet', 'Lemma', '05-15-1983', 'kl526', 'M',
'745-21-0321','3338 yy st', 'Miami', 'FL', '19376','2018-01-01'),
('PA010', 'Selam', 'Damtew', '09-22-1970', 's5561', 'F', '300-00-
2211','4651 ss st', 'Huston', 'TX', '11156','2018-09-10'),
('PA011', 'Simon', 'Kifle', '08-11-1968', 'dc256', 'M', '333-44-
5555','2287 sk st', 'Springfield', 'VA', '22132','2018-01-01'),
('PA012', 'Nany', 'Tekle', '08-25-1970', 'po724', 'F', '222-88-
4444','1313 nt st', 'Springfield', 'VA', '22132','2019-03-01'),
('PA013', 'Adane', 'Belay', '11-16-1984', 'sa366', 'M', '001-22-
3216','4687 ab st', 'Seattle', 'WA', '35800','2017-02-02'),
('PA014', 'Genet', 'Misikir', '05-28-1982', 'l8773', 'F', '999-
44-2299','00468 gm st', 'Richmond', 'VA', '55982','2017-11-12'),
('PA015', 'Mikiyas', 'Tesfaye', '01-15-1979', 'w6321', 'M', '221-
90-8833','5090 mt st', 'Alexandria', 'VA', '22132','2017-11-12'),
('PA016', 'Milki', 'Abishu', '01-16-2011', 'tr321', 'F', '221-90-
4444','1212 NW Flintridge rd ', 'Kansas city', 'MO', '64150','2018-10-12'),
('PA017', 'Fate', 'Tesfaye', '02-16-1979', 'v6341', 'F', '222-91-
8834','3419 NW 69 st', 'Kansas city', 'MO', '64151','2019-11-12'),
('PA018', 'Caltu', 'Bayisa', '04-17-1979', 'w6322', 'M', '221-90-
7733','4500 NW Flintirdge Rd', 'Kansas city', 'MO', '64150','2020-11-12'),
('PA019', 'Adane', 'Gebreigzehaber', '01-14-1980', 'w6561', 'F',
'555-90-8835','5090 mt st', 'Alexandria', 'VA', '22145','2017-11-12'),
('PA020', 'Miki', 'Tesfa', '01-18-1979', 'w7321', 'M', '777-90-
8833','5090 mt st', 'Alexandria', 'VA', '22155','2017-10-12'),
('PA021', 'Fantu', 'Kidus', '01-18-1979', 'tr6321', 'M', '888-90-
8833','5090 mt st', 'Alexandria', 'VA', '22156','2017-10-12');

-- Insert 5 more patients


GO

INSERT INTO Employee


VALUES ('EMP01', 'Neftalem', 'Medhanie', '050-23-1111', '1971-10-
07','M',78000,'2017-03-02','1293 Duncan Avenue', '198','Rockville', 'MD','20871',
'(707) 890-3212', 'nef@yahoo.com','P'),
('EMP02', 'Mark', 'Lewis', '060-23-2222', '1972-09-
12','M',67500,'2018-12-02','4080 Marshall Street', '800','Washington',
'DC','20021', '(202) 890-9032', 'mark@gmail.com','C'),
('EMP03', 'Dennis', 'Price', '060-21-3333', '1973-10-
09','F',89800,'2016-03-02','1331 Edsel Road', 'L21','Woodbridge', 'VA','20321',
'(570) 000-2112', 'kathe@gmail.com','M'),
('EMP04', 'Robert', 'Iversen', '070-23-4444', '1974-07-
01','M',100000,'2017-09-01','786 Eagle Lane', '234','Columbia', 'MD','20990',
'(301) 890-3200', 'rob@yahoo.com','P'),
('EMP05', 'Rosie', 'Seiler', '080-23-5555', '1975-03-
07','F',79300,'2016-03-02','123 Ky St', '698','Bethesda', 'MD','20871', '(332) 890-
3212', 'rosie@yahoo.com','A'),
('EMP06', 'Emmanuel', 'Kepa', '908-23-6666', '1985-09-
15','M',89800,'2018-12-02','5 Poe Lane', '832','Washington', 'DC','20021', '(204)
890-9032', 'emma@gmail.com','A'),
('EMP07', 'Andrew', 'Neftalem', '090-21-7777', '1986-11-
03','M',100100,'2015-03-02','1378 Gateway Road', '823','Alexandia', 'VA','20321',
'(703) 000-2112', 'dennisned@gmail.com','A'),
('EMP08', 'Liang', 'Porter', '111-23-8888', '1987-01-
01','M',78000,'2017-09-01','825 Victoria Street', '109','Columbia', 'MD','20990',
'(249) 890-3200', 'lian@yahoo.com','P'),
('EMP09', 'Sarah', 'Kathrin', '222-23-9999', '1988-03-
18','F',90800,'2014-03-02','1389 Finwood Road', '007','Germantown', 'MD','20871',
'(191) 890-3212', 'rosie@yahoo.fr','P'),
('EMP10', 'Christopher', 'Rasmussen', '333-23-0000', '1989-03-
23','M',62000,'2018-12-02','3520 Nash Street', '002','Washington', 'DC','20021',
'(320) 890-9032', 'chris@gmail.com','C'),
('EMP11', 'Ruth', 'Kumar', '444-21-1122', '1990-11-
24','F',90200,'2019-03-02','4656 Byrd Lane', 'L21','Arlington', 'VA','20321',
'(521) 000-2112', 'ruth@gmail.com','A'),
('EMP12', 'Stefan', 'Xu', '444-23-2233', '1990-09-
01','M',68000,'2013-09-01','3583 Stadium Drive', '100','Beltsville', 'MD','20990',
'(260) 890-3200', 'stef@yahoo.com','M'),
('EMP13', 'Jessamine', 'Seiler', '555-23-3344', '1982-11-
28','F',90200,'2018-03-02','1337 Havanna Street', '498','Clarksburg', 'MD','20871',
'(101) 890-3212', 'jes@yahoo.co.uk','M'),
('EMP14', 'Enza', 'Kepa', '666-23-4455', '1990-09-
30','F',85300,'2011-12-02','2780 Irish Lane', NULL,'Washington', 'DC','20021',
'(511) 890-9032', 'enz@gmail.com','C'),
('EMP15', 'Andrew', 'Kumar', '777-21-5566', '1983-10-
25','M',120800,'2010-03-02','3048 James Avenue', 'L21','Fairfax', 'VA','20321',
'(911) 000-2112', 'andkum@gmail.com','P'),
('EMP16', 'Ermias', 'Henriksen', '888-23-6677', '1983-09-
16','M',78000,'2017-09-01','714 Chicago Avenue', NULL,'Laurel', 'MD','20990',
'(199) 890-3200', 'ermias@yahoo.com','P'),
('EMP17', 'Petra', 'Seiler', '123-23-3456', '1980-09-
07','F',45000,'2018-03-02','123 Ky St', '198','Clarksburg', 'MD','20871', '(101)
890-3212', 'ps@yahoo.com','P'),
('EMP18', 'Peter', 'Kepa', '908-23-3432', '1990-09-
07','M',72300,'2018-12-02','907 12 St', NULL,'Washington', 'DC','20021', '(201)
890-9032', 'pk@gmail.com','C'),
('EMP19', 'Dennis', 'Kumar', '093-21-3456', '1983-10-
03','M',120800,'2019-03-02','123 Ky St', 'L21','Manassas', 'VA','20321', '(571)
000-2112', 'dk@gmail.com','P'),
('EMP20', 'Gang', 'Xu', '903-23-9056', '1983-09-01','M',79300,'2017-
09-01','213 Coles rd', NULL,'Columbia', 'MD','20990', '(240) 890-3200',
'gxu@yahoo.com','P'),
('EMP21', 'xumbi', 'Ja', '903-23-9056', '1988-09-
01','M',79301,'2018-09-01','213 Coles rd', NULL,'Columbia', 'MD','20990', '(240)
890-3200', 'xumbja@yahoo.com','P'),
('EMP22', 'Yemi', 'Ka', '816-23-9056', '1999-09-01','F',79302,'2019-
09-01','64th St', NULL,'Columbia', 'MD','22290', '(240) 899-3200',
'yemika@yahoo.com','P'),
('EMP23', 'Heni', 'Hu', '913-23-9056', '2001-09-01','M',79304,'2020-
09-01','4715NW Flintridge rd', NULL,'Kansas city', 'MD','20390', '(816) 890-3200',
'henihu@yahoo.com','P'),
('EMP24', 'Gigi', 'Fe', '816-67-9056', '1978-09-01','F',79308,'2021-
09-01',' 65th rd', NULL,'Columbia', 'MD','20590', '(240) 891-3200',
'gigife@yahoo.com','P'),
('EMP25', 'Eyob', 'Df', '913-56-9056', '2003-09-01','M',79305,'2022-
09-01','215 Coles rd', NULL,'Columbia', 'MD','20790', '(240) 897-3200',
'eyobfa@yahoo.com','P'),
('EMP26', 'Fante', 'TY', '913-78-8756', '2008-09-
01','M',79307,'2015-09-01','216 Coles rd', NULL,'Columbia', 'MD','20890', '(240)
898-3200', 'fantety@yahoo.com','P'),
('EMP27', 'Geb', 'Uk', '816-55-9056', '2007-09-01','M',79310,'2014-
09-01','217 Coles rd', NULL,'Columbia', 'MD','20290', '(240) 895-3200',
'yuka@yahoo.com','P'),
('EMP28', 'Giya', 'NB', '913-90-9056', '2016-09-01','M',79306,'2013-
09-01','222 Coles rd', NULL,'Columbia', 'MD','20590', '(240) 860-3200',
'giyanb@yahoo.com','P');
-- Insert 8 more employees
GO

INSERT INTO Doctor


VALUES ('EMP10','MD01', 'KNO-09-6667','2017-09-10', 'Senior','Infectious
Disease'),
('EMP12','MD02', 'BAV-00-9456','2016-08-10', 'senior','Family
medicine'),
('EMP04','MD03', 'LIC-22-0678', '2015-12-31','Senior','Intenal
Medicine'),
('EMP17','MD04', 'KAL-16-5420','2018-09-
03','Junior','Cardiologist'),
('EMP15','MD06', 'XYZ-66-7601','2017-02-5', 'Junior','Infectious
Disease'),
('EMP27','MD07', 'XYZ-77-7602','2020-02-5', 'Junior','Infection
surgery'),
('EMP26','MD08', 'XYZ-99-7603','2021-02-5', 'Junior','Pediatrics'),
('EMP28','MD09', 'XYZ-87-7607','2007-02-5',
'Junior','Dermatology');

-- Insert 3 more doctors (from the 8 employees you inserted above)


GO

INSERT INTO Nurse


VALUES ('EMP16','NU01','GHO-10-5567','2021-10-01','Senior','Midwife'),
('EMP03','NU02','ABC-11-4545','2007-12-11','Junior','Radiologist'),
('EMP05','NU03','DEC-13-3432','2022-11-11','Senior','Anesthestic'),
('EMP08','NU04','EDS-12-1122','2008-10-09','Junior','Practitioner');

INSERT INTO Department


VALUES ('EMP11','REG','HEAD'),
('EMP12','REG','MANAGER'),
('EMP13','REG','HEAD');

INSERT INTO Diagnosis


VALUES (1, 'PA003', 'MD03', 1, '2017-11-06', 'Positive'),
(2, 'PA009', 'MD02', 5, '2018-02-06', 'Positive'),
(3, 'PA012', 'MD01', 2, '2015-09-04', 'Negative'),
(4, 'PA005', 'MD02', 3, '2019-11-06', 'Negative'),
(5, 'PA014', 'MD04', 4, '2014-10-04', 'Negative'),
(6, 'PA001', 'MD02', 5, '2017-10-04', 'Positive'),
(7, 'PA004', 'MD01', 6, '2016-11-04', 'Positive'),
(8, 'PA011', 'MD03', 2, '2016-11-04', 'Positive'),
(9, 'PA001', 'MD04', 2, GETDATE(),'Positive'),
(10,'PA002', 'MD03', 3, GETDATE(),'Not conclusive'),
(11,'PA003', 'MD02', 3, GETDATE(),'Negative'),
(12,'PA004', 'MD01', 3, GETDATE(),'Not conclusive'),
(13,'PA005', 'MD02', 2, GETDATE(),'Positive'),
(14,'PA006', 'MD03', 2, GETDATE(),'Not conclusive'),
(15,'PA007', 'MD04', 1, GETDATE(),'Positive'),
(16,'PA008', 'MD03', 3, GETDATE(),'Not conclusive'),
(17,'PA009', 'MD11', 4, GETDATE(),'Positive'),
(18,'PA0010', 'MD12', 1, GETDATE(),'Negative'),
(19,'PA0011', 'MD13', 2, GETDATE(),'Positive'),
(20,'PA0012', 'MD14', 3, GETDATE(),'Not conclusive'),
(21,'PA0013', 'MD15', 6, GETDATE(),'Positive'),
(22,'PA0014', 'MD06', 8, GETDATE(),'Positive'),
(23,'PA0015', 'MD17', 1, GETDATE(),'Not conculsive'),
(24,'PA0016', 'MD19', 2, GETDATE(),'Positive'),
(25,'PA0017', 'MD20', 3, GETDATE(),'Positive'),
(26,'PA0018', 'MD21', 5, GETDATE(),'Positive'),

-- Insert 10 more diagnosis


GO

INSERT INTO Prescription


VALUES (10, 1, '2019-01-02'),
(11, 2, '2017-06-02'),
(12, 3, '2018-01-02'),
(13, 9, '2019-04-2'),
(14, 13, '2016-09-12'),
(15, 7, '2019-03-25'),
(16, 14, '2019-03-26'),
(17, 16, '2019-03-27'),
(18, 8, '2019-03-26'),
(19, 8, '2019-03-26'),
(20, 22, '2020-03-26'),
(21, 10, '2021-03-26'),
(22, 11, '2019-05-26'),
(23, 12, '2019-06-26'),
(24, 13, '2019-03-23'),
(25, 6, '2019-03-29'),
(26, 5, '2019-03-21'),
(27, 23, '2007-03-26'),
(28, 7, '2008-03-26');

-- Insert 10 more precsriptions


GO

INSERT INTO MedicinePrescribed


VALUES (10, 3,'As you wish', 10),
(14, 2,'As you wish', 12),
(12, 5,'As you wish', 6),
(11, 1,'As you wish', 9),
(13, 4,'As you wish', 7),
(18, 4, '3 times daily', 3),
(17, 3, '2 times daily', 2),
(10, 5, '2 times a day', 3),
(12, 1, '3 times daly', 2),
(18, 3, '6 times daily', 3),
(23, 5, '1 times daly', 2),
(25, 3, '3 times daly', 1),
(15, 1, '3 times daly', 2),
(29, 7, '3 times daly', 2),
(27, 8, '2 times daly', 3),
(28, 1, '3 times daly', 2),
(18, 4, '1 times daly', 1),
(22, 5, '3 times daly', 2),
(25, 9, '2 times daly', 1);

-- Insert 10 more medicens prescribed


GO

INSERT INTO PharmacyPersonel


VALUES ('EMP02', 'GP-003', '2012-02-06', 86, 'Senior'),
('EMP06', 'CP-073', '2014-04-13', 93, 'Junior'),
('EMP08', 'AB-099', '2017-02-16', 93, 'Junior'),
('EMP21', 'AB-059', '2020-02-16', 83, 'Junior'),
('EMP22', 'AB-880', '2017-02-16', 63, 'Junior'),
('EMP23', 'AB-555', '2022-02-16', 73, 'Junior');

-- Insert 3 more Pharmacy personnel (from the 8 employees you inserted above)
GO

/****************** The SELECT Statement *****************************

SELECT statement
- SELECT statement is used to query tables and views,

SYNTAX :
SELECT select_list [ INTO new_table ]
[ FROM table_source ]
[ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]

Has has the following clauses inside,


- FROM clause
: specifies the source of data, table or view
- WHERE clause
: search condition / criteria
- GROUP BY clause
: group by list
- HAVING clause
: search condition / criteria for out put of GROUP BY clause
- ORDER BY clause
: specify the condition to sort results

Sequence of execution/evaluation of SELECT statement.


1st : FROM clause
2nd : WHERE clause
3rd : GROPUP BY clause
4th : HAVING clause
5th : SELECT
6th : ORDER BY clause

IMPORTANT : To avoid erros in tables/views name resoulution, it is best to include


schema and object name

If the table/view contains irregular characters such as spaces or


other
special characters, you need to delimit, or enclose the name,
either by
using " " or [ ]

End all statements with semicolon (;) character. It is optional


to use semi
colon to terminate SELECT statement, however future versions will
require
its use, therefore you should adopt the practice.
*/

USE HRMSDB

--EXERCISE # 01
--Write SELECT statement to retrive the entire columns of Employee table by
explicitly listing each column.
--NOTE (1) List all the columns to be retrived on SELECT statement
--NOTE (2) The name of each column must be separated by comma

SELECT
empId,empFName,empLName,SSN,DoB,gender,salary,employedDate,strAddress,apt,city,
[state],zipCode,phoneNo,email,empType
FROM Employee

--Repeat the previous exercise, but SSN and DoB must be displated as the 1st and
2nd column
--NOTE : The order of columns list determine their display, regardless of the order
of defination in source table.
SELECT
SSN,DOB,empId,empFName,empLName,gender,salary,employedDate,strAddress,apt,city,
[state],zipCode,phoneNo,email,empType
FROM Employee

--EXERCISE # 03
--Write SELECT statement to retrive the entire columns of Employee table using
"star" character (*)
--NOTE : This method is frequently used for quick test, refrain using this short
cut in production environment

SELECT *
FROM Employee

--EXERCISE # 04
--Write SELECT statement to retrive empId, empFName, empLName, phoneNo and email
columns of Employee table.

SELECT empId,empFName,empLName,phoneNo,email
FROM Employee

/*
--SELECT statement can be used to perform calculations and manipulation of data
Operators,
'+' : Adding or Concatinate
'-' : Subtract
'*' : Multiply
'/' : Divide
'%' : Modulo
The result will appear in a new column, repeated once per row of result set
Note : Calculated expressions must be Scalar, must return only single value
Note : Calculated expressions can operate on other colums in the same row
*/

SELECT 5 % 3

--EXAMPLE :
--Calculate the amount each type of medicine worth in stock

--EXERCISE # 05
--The unit price of each medicine is increased by 6%. Provide the list of medecine
with
--their respective rise in price.

SELECT mId,brandName,qtyInStock, SUM(unitprice * 6 + unitprice ) /100 AS [+6% New


Price]------?????
FROM medicine
GROUP BY mId,brandName,qtyInStock,unitPrice
--EXERCISE # 06
--Calculate and display the old and new prices for each medicine
SELECT mId,brandName,qtyInStock, SUM(unitprice * 6 + unitprice ) /100 AS [+6% New
Price]------?????
FROM medicine
GROUP BY mId,brandName,qtyInStock,unitPrice

--'+' Can be used to as an operator to concatenate (linked together as in a chain)


the content of columns
--EXAMPLE : Get Employee Full Name of all employees
SELECT CONCAT(empFName, ' ', empLName) AS [Full Name]
FROM Employee

--EXERCISE # 07
--Write a code to display employee's Full Address, and Phone Number
SELECT CONCAT(strAddress,' ', apt,' ', city,' ', [state],' ', zipCode) AS
[Address],phoneNo
FROM Employee

--CONCAT Function
--Is string function that joins two or more string values in an end-to-end manner.
--SYNTAX: CONCAT ( string_value1, string_value2, string_value2, ...)
--EXAMPLE : Write a code to display the Full Name of all employees using CONCAT
function

--EXERCISE # 08
--Write a code to display employee's Full Address, and Phone Number using CONCAT
function
SELECT CONCAT(strAddress,' ', apt,' ', city,' ', [state],' ', zipCode) AS
[Address],phoneNo
FROM Employee

/*
DISTINCT statement
SQL query results are not truly relational, are not always unique, and not
guranteed order
Even unique rows in a source table can return duplicate values for some
columns
DISTINCT specifies only unique rows to apper in result set
--
*/

--EXAMPLE :
--Write a code to retrive the year of employement of all employees in Employee
table
SELECT employedDate
FROM Employee

--Notice there are redudant instances on the result set. Execute the following code
--and observer the change of result set

--EXERCISE # 09
--Write a code that retrive the list of dosages from MedicinePrescribed table, use
DISTINCT to eliminate duplicates

SELECT DISTINCT dosage


FROM MedicinePrescribed
/*
Column Aliases
- At data display by SELECT statement, each column is named after it's
source.
- However, if required, columns can be relabeled using aliases
- This is useful for columns created with expressons
- Provides custom column headers.

Table Aliases
- Used in FROM clause to provide convenient way of refering table elsewhere
in the query, enhance readability

*/

--EXAMPLE :
--Display all columns of Disease table with full name for each column
SELECT dId,dName,dCategory,dType
FROM Disease

--EXERCISE # 10
--Write the code to display the 10% rise on the price of each Medicine, use
appropriate column alias for comoputed column
SELECT mId,brandName,qtyInStock, SUM(unitprice * 10 + unitprice ) /100 AS [+10% New
Price]------?????
FROM medicine
GROUP BY mId,brandName,qtyInStock,unitPrice

--EXERCISE # 11
--Modify the above code to include the new price column with the name 'New Price'

SELECT mId,brandName,qtyInStock, SUM(unitprice * 6 + unitprice ) /100 AS [New


Price]------?????
FROM medicine
GROUP BY mId,brandName,qtyInStock,unitPrice

--EXAMPLE :
--Using '=' signs to assign alias to columns

--EXERCISE # 12
--Use '=' to assign alias for the new price of all medecines with price rise by 13%
SELECT mId,brandName,qtyInStock, SUM(unitprice * 13) /100 + unitprice AS [New
Price]------?????
FROM medicine
GROUP BY mId,unitPrice

--EXAMPLE :
--Using built in function on a column in the SELECT list. Note the name of column
is used as input for the function

--EXAMPLE :
--Write a code to display the the first name and last name of all patients. Use
table alias to refer the columns
SELECT *
FROM Patient

SELECT pFName, pLName


FROM Patient

--EXERCISE # 13
--Assign the appropriate aliases for columns displayed on previous exercise.
SELECT pFName , pLName
FROM Patient

/*
Logical Processing Order on Aliases
- FROM, WHERE, and HAVING clauses process before SELECT
- Aliases created in SELECT clauses only visible to ORDER BY clause
- Expressions aliased in SELECT clause may be repeated elsewere in query

5. SELECT [DISTINCT | ALL] 7.[TOP <value> [PERCENT]] <column list>


1. FROM
2. WHERE
3. GROUP BY
4. HAVING
6. ORDER BY
*/

-- September 26, 2020

--EXAMPLE
--The following code will run free from error, since alias dicleration done before
alias used by ORDER BY clause

--EXAMPLE
--The following code will err out, since alias decleration done after the execution
of WHERE clause
SELECT empId AS [Employee ID], empFName AS [First Name], empLName AS [Last Name]
FROM Employee
WHERE [empFName] LIKE 'R%'

/*
Simple CASE Expression
- Can be used in SELECT, WHERE, HAVING AND ORDER BY clauses
- Extends the ability of SELECT clause to manipulate data as it is retrived
- CASE expression returns a scalar (single-valued) value based on conditional
logic

- In SELECT clause, CASE behaves as calculated column requiring an alias


- Forms of CASE expressions
- Simple CASE
: Compares one value to list of possible values, returns first
match
- Searched CASE
: Evaluate a set of logical expressions & returns value found in
THEN clause

CASE Statement Syntax:


CASE <column name>
WHEN <value one> THEN <output one>
WHEN <value two> THEN <output two>
.
.
.
ELSE <default output>
END <new alias>

*/

--EXAMPLE :
--Simple CASE
/*
First
ALTER TABLE Disease
DROP COLUMN dCategory
*/
SELECT * FROM Disease

SELECT dId, dName,dCategory,


CASE dType
WHEN 'contageous' THEN 'X'
WHEN 'XYZ' THEN 'Y'
WHEN 'CHRONIC' THEN 'Z'
ELSE 'NO CATEGORY'
END AS [Dis category detail]
FROM Disease

--EXAMPLE :
--Searched CASE
use HRMSDB

--EXERCISE # 14
--Use simple CASE to list the brand names of medecines available as per Medecine Id
SELECT *
FROM Medicine
SELECT mId,brandName,
(CASE brandName
WHEN 'xaleto' THEN 'Y'
WHEN 'Hexalen' THEN 'Z'
END) AS [brandName IN FULL] -----????
FROM Medicine
--EXERCISE # 15
--Searched CASE to identify label the price of a medicine cheap, moderate and
expensive. Price of cheap ones
--is less than 15 USD, and expensive ones are above 45 USD. Display Medecine Id,
Generic Name, the unit price and
--category of the price.
SELECT mId,unitPrice,genericName,
(CASE
WHEN unitPrice >45.00 THEN 'Expensive'
WHEN unitPrice <15.00 THEN 'Cheap'
ELSE 'Moderate'
END) AS [Category of price]
FROM Medicine

-- Display MRN, Full Name and Gender (as Female and Male) of all Patients -- use
case statement for gender
SELECT mrn,pFName,pLName,
(CASE gender
WHEN 'F' THEN 'Female'
WHEN 'M' THEN 'Male'
END) AS [Gender In Full]
FROM patient
/*
SORTING DATA
- Used to desplay the output of a query in certain order
- Sorts rows in results for presentation purpose
- Uses ORDER BY clause
- ORDER BY clause
- The last clause to be logically processed in SELECT statement
- Sorts all NULLs together
- Refers to columns by name, alias or ordinal position (not
recommended)
- Declare sort order with ASC or DESC

- SYNTAX :
SELECT <select_list>
FROM <table_source>
ORDER BY <order_by_list> [ASC|DESC]
*/

-- Get Employees earning less that 75000.00


SELECT *
FROM Employee
WHERE salary <75000.00
-- Get Patients not in DC Metro Area (not DC, MD, VA)
SELECT *
FROM Patient
WHERE city <> ('DC')

-- Get patients from FL, VA and TX


SELECT *
FROM Patient
WHERE city IN ('FL','VA','TX')

-- Get patients Female Patients from FL, VA and TX


SELECT *
FROM Patient
WHERE gender = 'F'

--ORDER BY clause using column names


--EXAMPLE : Retrive details of Employees in assending order of their first names

-- Also order by last name - and return the names as lastname, firstname

--EXERCISE # 16
--Write a code to retrive details of Patients in assending order of last names
SELECT pLName
FROM Patient
GROUP BY pLName
use HRMSDB

--EXERCISE # 17
--Write a code to retrive details of Employees in descending order of DoB
--Note : Use column alias on ORDER BY clause
SELECT DoB
FROM Employee
GROUP BY DoB
ORDER BY 1 DESC

--EXAMPLE :
--ORDER BY clause can uses more than one column

/* Some Date related built in functions


GETDATE() -- Returns datetime
YEAR() -- returns integer
MONTH() -- returns integer
DAY() -- returns integer

*/

--EXERCISE # 18
--Display the list of Patients in the order of the year of their treatement. Use
their First name to order the ones that came
--to the hospital on same year.

SELECT registeredDate,pFName
FROM Patient
GROUP BY registeredDate,pFName

-- Return the year, month and day separately

/*
FITERING DATA
- Used to retrive only a subset of all rows stored in the table
- WHERE clause is used to limit which rows to be retured
- Data filtered server-side, can reduce network trafic and client memory
usage

-WHERE clause
- use predicates, expressed as logical conditions
- rows which predicate evaluates to TRUE will be accepted
- rows of FALSUE or UNKNOWNS filitered out
- in terms of precidence, it follows FROM clause
*** - can't see the alias declared in SELECT clause
- can be optimized to use indexes

SYNTAX : (WHERE clause only )


WHERE <search_condition>

- PREDICATES and OPERATORS


- IN : Determines whether a specified value matches any value in
the subquery or list
- BETWEEN : Specifies an inclusive range to test
- LIKE : Determines whether a specific character string matches a
specified pattern
- AND : Combines two Boolean expressions and returns TRUE only
when both are TRUE
- OR : Combines two boolean expressions and returns TRUE if
either is TRUE.
- NOT : Reverses the result of a search condition.

*/

--EXAMPLE :
--Find below a code to get Employee information (across all columns) - who are
contractors,
--Note : P: Principal Associate, A: Associate, C: Contractor, M:Manager

--EXAMPLE :
--Find below a code to get Employee information (across all columns) - for
Contract and Associate

--EXERCISE # 19
--Find the list of employees with salary above 90,000
SELECT *
FROM Employee
WHERE salary >90000.00

--EXERCISE # 20
--Find the list of employees with salary range betwen 85,000 to 90,000 inclusive
SELECT *
FROM Employee
WHERE salary BETWEEN 85000.00 AND 90000.00

--EXERCISE # 21
--Find the list of patients that had registration to the hospital in the year 2018
--Use 'BETWEEN' operator
SELECT *
FROM Patient
WHERE registeredDate BETWEEN '2018-01-01' AND '2018-12-31'

-- The above two queries are efficient ones


-- The query below will also return the same result - but considered inefficient
(issue related to indexing)

--EXERCISE # 22
--Get Employees born in the year 1980 (from 1980-01-01 - 1980-12-31)using 'BETWEEN'
operator
SELECT *
FROM Employee
WHERE DoB BETWEEN '1980-01-01' AND '1980-12-31'

--EXERCISE # 23
--Get Employees born in the year 1980 using 'AND' operator
SELECT *
FROM Employee
WHERE DoB BETWEEN '1980-01-01' AND '1980-12-31'

--We can also use the YEAR() function to do the same for the above exercise - but
it is NOT recommended

--EXERCISE # 24
--Write a code that retrives details of Patients that live in Silver Spring.
SELECT *
FROM Patient
WHERE city IN ('Silver Spring')

--EXERCISE # 25
--Write a code retrive the information of contractor Employees with salary less
than 75000.

SELECT *
FROM Employee
WHERE salary <75000.00

--EXERCISE # 26
--Write a code to retrive list of medicines with price below 30 USD.
SELECT *
FROM Medicine
WHERE unitPrice <30.00 ---- Re insert data

--EXERCISE # 27
--Write a code to retrive patients that live in Miami and Seattle
SELECT *
FROM Patient
WHERE city IN ('Miami','Seattle')

--EXERCISE # 28
--Write a code to retrive patients that are not living in Silver Spring
SELECT *
FROM Patient
WHERE city <> ('Silver Spring')

/*
STRING FUNCTIONS

- CONCATENATE
- Returns a character string that is the result of concatenating
string_exp2 to string_exp1.
- SYNTAX
CONCAT( string_exp1, string_exp2, ...)

- LEFT
- Returns the leftmost count characters of string_exp.
- SYNTAX
LEFT( string or string_exp, number_of_characters )

Get three characters from the left of 'Richards'


Ans: 'Ric'

- RIGHT
- To extract a substring from a string, starting from the right-most
character.
- SYNTAX
RIGHT( string or string_exp, number_of_characters )

Get three characters from the right of 'Richards'


Ans: 'rds'

- CHARINDEX
- returns the location of a substring in a char/string, from the left
side.
- The search is NOT case-sensitive.
- SYNTAX :
CHARINDEX( substring, string, [start_position] )

-> given a string and character CHARINDEX function returns the relative
location (index) of the first occurrence of that character in the string

e.g. thus the CHARINDEX OF 'g' IN String: 'Johansgurg' is 7

-LENGTH
- Returns the number of characters in string_exp, excluding trailing
blanks.
- SYNTAX
LEN( string or string_exp )
e.g. LEN ('Complete') -> 8

-LTRIM function
- removes all space characters from the left-hand side of a string.
- SYNTAX
LTRIM( string_exp )
- RTRIM
- removes all space characters from the right-hand side of a string.
- SYNTAX
RTRIM( string_exp )
- TRIM
- removes all space characters from the both sides of a string.
- SYNTAX
TRIM( string_exp )

Check the following link for complete list of String Functions

https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/string-
functions?view=sql-server-2017

*/

SELECT *
FROM Employee
--EXERCISE # 29
--Write a code to display full name for employees
SELECT empFName+'', +empLName AS [full name]
FROM Employee

--EXERCISE : 30
--Get the last four digists of SSN of all Employees together with their id and full
name
SELECT empFName+'', +empLName AS [full name],empId, RIGHT(SSN,4) AS [last four of
social]
FROM Employee

-- Question Write a query to get the Employee with the last four digits of the SSN
is '3456'

-- Q2 - Write a query to get the Employee with the last four digits of the SSN is
'3456' and with DoB = '1980-09-07'

--EXERCISE # 31
--Write a code to retrive the full name and area code of their phone number, use
Employee table
SELECT empFName+' '+empLName AS [Full Name], LEFT (phoneNo,5) AS [Area code]
FROM Employee
ORDER BY[Full Name]

--EXERCISE # 32
--Write a code to retrive the full name and area code of their phone number,
(without a bracket). use Employee table
SELECT empFName+' '+empLName AS [Full Name], SUBSTRING (phoneNo,2,3) AS [Area code]
FROM Employee
ORDER BY[Full Name]
--EXAMPLE # 33
--Run the following codes and explain the result with the purpose of CHARINDEX
function
SELECT CHARINDEX('O', 'I love SQL')

---return 4 i.e counted from left to right, the index of the first accurance of '0'

--EXERCISE # 34
--Modify the above code, so that the output/result will have appopriate column name
SELECT CHARINDEX('O', 'I love SQL') AS [Index for letter 'O']
SELECT CHARINDEX (' ', '9 mccormick circle') -------???

--EXAMPLE # 35
--Write a code that return the index for letter 'q' in the sentence 'I love sql'
SELECT CHARINDEX('q', 'I love SQL') [Index for letter 'Q']

--EXERCISE # 36
--Use the CHARINDEX() function to retrieve the house(building) number of all our
employees
SELECT *
FROM Employee
SELECT CHARINDEX(' ',apt)
FROM Employee ------------------------????

--EXAMPLE :
--Run the following code and explain the result with the purpose of LEN function
SELECT LEN('I love SQL') -------10
--- the LEN() function mainly returns the length of a string

--EXAMPLE :
--Reterive the email's domain name for the entiere employees.
--NOTE : Use LEN(), CHARINDEX() and RIGHT()

--EXERCISE # 37
--Assign a new email address for empId=EMP05 as 'sarah.Kathrin@aol.us'
UPDATE Employee
SET email = 'sarah.Kathrin@aol.us'
WHERE empId = 'EMP05'

--EXERCISE # 38
--Using wildcards % and _ ('%' means any number of charactes while '_' means single
character)
--mostly used in conditions (WHERE clause or HAVING clause)
--Get Employees whose first name begins with the letter 'P'
SELECT *
FROM Employee
WHERE empFName LIKE 'P%'

--EXERCISE # 39
--Get the list of employees with 2nd letter of their frst name is 'a'
SELECT *
FROM Employee
WHERE empFName LIKE '_a%'

--EXERCISE # 40
--Get full name of employees with earning more than 75000. (Add salary information
to result set)
SELECT empFName+'', +empLName AS [full name],salary
FROM Employee
WHERE salary >75000.00
--EXERCISE # 41
--Get Employees who have yahoo email account
--NOTE : the code retrives only the list of employee's with email account having
'yahoo.com'
SELECT *
FROM Employee
WHERE email LIKE 'yahoo.com'

--EXERCISE # 42
--Get Employees who have yahoo email account
--NOTE : Use RIGHT string function.

--EXERCISE # 43
--Get Employees who have yahoo email account
--NOTE : The code must checke only 'yahoo' to retrive the entire employees with
yahoo account

--EXERCISE # 44
--Create a CHECK constraint on email column of Employee table to check if it's a
valid email address
--NOTE : Assume a valid email address contains the '@' character

/* Aggregate Functions

COUNT() - returns the number of rows satisfying a given condition


(conditions)
AVG() - Returns the arithimetic mean (Average) on a set of numeric values
SUM() - Returns the Sum of a set of numeric values
MIN() - Returns the Minimum from a set of numeric values
MAX() - Returns the Maximum from a set of numeric values
STDEV() - Returns the Standard Deveiation of a set of numeric values
VAR() - Returns the Variance of a set of numeric values
*/

--EXERCISE # 45
--Get total number of Employees

--EXERCISE # 46
--Get number of Employees not from Maryland

--OR
--EXERCISE # 47
--Get the number of Principal Employees, with emptype = 'P')

--EXERCISE # 48
--Get the Minimum salary

--EXERCISE # 49
--Modify the above code to include the Minimum, Maximum, Average and Sum of the
Salaries of all employees

--EXERCISE # 50
--Get Average Salary of Female Employees

--EXERCISE # 51
--Get Average Salary of Associate Employees (empType = 'A')

--EXERCISE # 52
--Get Average salaries for each type of employees?

--EXERCISE # 53
--Get Average Salary per gender

--EXERCISE # 54
--Get Average Salary per sate of residence

--EXERCISE # 55
--Get Employees earning less than the average salary of all employees

/*
NOTE : An aggregate may not appear in the WHERE clause unless it is in a subquery
contained in a
HAVING clause or a SELECT list, and the column being aggregated is an outer
reference.

SUBQUERIES
- Is SELECT statement nested within another query, (queries within queries)
- Can be Scalar, multi-valued, or table-valued
- Scalar subquery : return single value, outer queries handle only
single result
- Multi-valued : return a column table, outer queries must be able to
handle multipe results
- The result of inner query (subquery) are returned to the outer query
- Enables to enhance ability to create effective queries
- Can be either Self-Contained or Correlated
- Self-Contained
- have no dependency to outer query
- Correlated
- one or more column of subquery depends on the outer query.
- Inner query receives input from the outer query & conceptually
executes once per row in it.
- Writing correlated subqueries
- if inner query is scalar, use comparision opetators as '=',
'<', '>', and '<>'in WHERE clause
- if inner query returns multi-values, use and 'IN' predicate
- plan to handle 'NULL' results as required.

*/

--EXERCISE # 58
--Get list of Employees with earning less than the average salary of Associate
Employees
--Note : Use a scalar subquery which is self contained to solve the problem

--EXERCISE # 59
--Get Principal Employees earning less than the average of Contractors

--EXERCISE # 60
--Get Principal Employees earning less than or equal to the average salary of
Pricipal Employees

--EXERCISE # 61
--Get Contractors earning less than or equal to the average salary of Contractors

--EXERCISE # 62
--Get Associate Employees earning less than or equal to the average salary of
Associate Employees

--EXERCISE # 63
--Get Managers earning less than or equal to the average salary of Managers

--EXERCISE # 64
--Get the count of Employees based on the year they were born

--EXERCISE # 65
--Get list of patients diagnoized by each doctor
--NOTE : Use multi-valued subquery to get the list of doctors from 'Doctors' table

/*
Note : Here is the logical structure of the outer query for the above example
Subqueries that have multi-values will follow the same fashion

SELECT docId,MRN,diagDate,diagResult
FROM Diagnosis AS D
WHERE D.docId IN ( MD01, MD02, MD03, MD04 )
ORDER BY DOCID

*/

--EXERCISE # 67
--Get list of patients diagnoized for each disease type
--NOTE : Use multi-valued subquery to get the list of disease from 'Disease' table

--EXAMPLE :
--Get Employees who are earning less than or equal to the average salary of their
gender
--NOTE : Use correlated subquery

--EXERCISE # 68
--Retrieve all Employees earning less than or equal to their groups averages
--NOTE : Use correlated subquery,

--EXAMPLE
--Better way to deal with previous exercise is to use 'JOIN', run the following and
confirm
--try to analizye how the problem is sloved, the next section try to introduce
about JOINing tables

-- Create one table called - Department (depId, depName, depEstablishmentDate)


-- And also allocate our employees to the departments
USE HRMSDB;
GO
CREATE TABLE Department
(
depId CHAR(4) PRIMARY KEY NOT NULL,
depName VARCHAR(40) NOT NULL,
depEstablishmentDate DATE
);
GO
INSERT INTO Department VALUES ('KB10', 'Finance', '2010-10-10'), ('VL20',
'Marketing', '2010-01-10'), ('HN02', 'Medicine', '2010-01-10'),
('AK12', 'Information Technology',
'2015-01-01')
GO
ALTER TABLE Employee
ADD department CHAR(4) FOREIGN KEY REFERENCES Department(depId)
GO
UPDATE Employee
SET department = 'HN02'
WHERE empId IN ('EMP10','EMP12','EMP04','EMP17','EMP15')

UPDATE Employee
SET department = 'KB10'
WHERE empId IN ('EMP01', 'EMP02', 'EMP03')

UPDATE Employee
SET department = 'VL20'
WHERE empId IN
('EMP05',
'EMP06',
'EMP07',
'EMP08',
'EMP09');
GO
UPDATE Employee
SET department = 'AK12'
WHERE department IS NULL

--EXERCISE # 56
--Note : The answer for the this exercise will be used as subquery to the next
question )
--Get the average salary of all employees

--EXERCISE # 56.1
-- Get the average salary of employees in each department

--EXERCISE # 57
--Get the list of employees with salary less than the average employee's salary
--Note : Use a scalar subquery which is self contained to solve the problem

-- EXERCISE 57 -1
-- Get Employees earning less than or equal to the average salary of thier
corresponding departments
-- We do this in diferent ways
---- Let's use Correlated sub-query
-- First let's do this one by one
---- Q1: Get Employees working in department 'AK12' and earning less than or equal
to the departmental average salary

--- Q2: Get Employees working in department 'HN02' and earning less than or equal
to the departmental average salary

--- Q3: Get Employees working in department 'KB10' and earning less than or equal
to the departmental average salary

--- Q4: Get Employees working in department 'VL20' and earning less than or equal
to the departmental average salary

-- The question is to create one query that returns all the above together

/*
Using 'EXISTS' Predicate with subqueries
- It evaluates whether rows exist, but rather than return them, it returns
'TRUE' or 'FALSE'
- Useful technique for validating data without incurring the overhead of
retriving and counting the results
- Database engine optimize execution for query having this form
*/

--EXAMPLE
--The following code uses 'EXIST' predicate to display the list of doctors that
diagnose a patient

--EXERCISE # 69
--Modify the above code to display list of doctor/s that had never diagnosed a
patient

--EXERCISE # 70
--Write a code that display the list of medicines which are not prescribed to
patients

--EXERCISE # 71
--Write a code that display the list of medicines which are prescribed to patients

/************ Working with Multiple Tables

Usually it is required to query for data stored in multiple locations,


Creates intermediate virtual tables that will be consumed by subsequent phases or
the query

- FROM clause determines source of table/s to be used in SELECT statement


- FROM clause can contain tables and operators
*** - Resulst set of FROM clause is virtual table
: Subsequent logical operations in SELECT statement consume this
virtual table
- FROM clause can establish table aliases for use by subsequent pharses of
query

- JOIN : is a means for combining columns from one (self-join) or more tables
by using values
common to each.

- Types of JOINs
CROSS JOIN :
: Combines all rows in both tables (Creates Carticial product)
INNER JOIN ( JOIN )
: Starts with Cartecian product, and applies filter to match rows
between tables based on predicate
: MOST COMMONLY USED TO SOLVE BUSINESS PROBLEMS.
OUTER JOIN
: Starts with Cartician product, all rows from designated table
preserved,
matching rows from other table retrived, Additional NULL's
inserted as
place holders

: Types of OUTER JOIN


: LEFT OUTER JOIN ( LEFT JOIN )
- All rows of LEFT table is preserved,
: RIGHT OUTER JOIN ( RIGHT JOIN )
- All rows of RIGHT table is preserved,
: FULL OUTER JOIN ( FULL JOIN )

*/

--For demonstration purpose, run the following codes that creates two tables, T1
and T2
--After inserting some data on each tables view the cross product, 'CROSS JOIN' of
the two tables

CREATE TABLE T1
( A CHAR(1),
B CHAR(1),
C CHAR(1)
);
GO

CREATE TABLE T2
( A CHAR(1),
Y CHAR(1),
Z CHAR(1)
);
GO

INSERT INTO T1
VALUES ('a','b','c'),
('d','e','f'),
('g','h','i');
GO

INSERT INTO T2
VALUES ('a','m','n'),
('X','Y','Z'),
('d','x','f');

GO

--First see the content of each table one by one

--Now get the Cross Product (CROSS JOIN) of T1 and T2

--Execute the following to get LEFT OUTER JOIN b/n T1 and T2 with condition columns
'A'
--on both tables have same value
--Execute the following to get RIGHT OUTER JOIN b/n T1 and T2 with condition
columns 'A'
--on both tables have same value, Notice the difference with LEFT OUTER JOIN

--Execute the following to get FULL OUTER JOIN b/n T1 and T2 with condition columns
'A'
--on both tables have same value, Again notice the difference with LEFT/RIGHT OUTER
JOINs

--EXERCISE # 72
--Get the CROSS JOIN of Patient and Diagnosis tables

--EXERCISE # 73
--Get the information of a patient along with its diagnosis.
--NOTE : First CROSS JOIN Patient and Diagnosis tables, and retrive only the ones
that share the same 'mrn on both tables

--EXERCISE # 74
-- Retrive MRN, Full Name, Diagnosed Date, Disease Id, Result and Doctor Id for
Patient, MRN = 'PA002'

--EXAMPLE :
--LEFT OUTER JOIN : Returns all rows form the first table, only matches from second
table.
--It assignes 'NULL' on second table that has no matching with first table

--EXERCISE :
--List employees that are not doctors by profession
--NOTE : Use LEFT OUTER JOIN as required

--EXAMPLE :
--RIGHT OUTER JOIN : Returns all rows form the second table, only matches from
first table.
--It assignes 'NULL' on second table that has no matching with second table
--The following query displays the list of doctors that are not employees to the
hospital

--Obviously all Doctors are employees, hence the result has no instance.

--EXAMPLE : The following query displays the list of doctors that had never
diagnosed
--a parient

--EXERCISE # 75
--Display the list of medicines that are prescribed by any of the doctor. (Use
RIGHT OUTER JOIN)

--EXERCISE # 76
--Display the list of medicines that which not prescribed by any of the doctors.
(Use RIGHT OUTER JOIN)

--EXERCISE # 77
--Get Patients with their diagnosis information: MRN, Full Name, Insurance Id,
Diagnosed Date, Disease Id and Doctor Id
--You can get this information from Patient and Diagnosis tables

--EXERCISE # 78
--Get Doctors who have ever diagonosed a patient(s) with the diagnosis date, mrn
--and Disease Id and result of the patient who is diagnosed
--The result should include Doctor Id, Specialization, Diagnosis Date, mrn of
--the patient, Disease Id, Result

--EXERCISE # 79
--Add the Full Name of the Doctors to the above query.
--HINT : Join Employee table with the existing table formed by joining Doctor &
Diagnosis tables on previous exercise

--EXERCISE # 80
--Add the Full Name of the Patients to the above query.

--EXERCISE # 81
--Add the Disease Name to the above query

--EXERCISE # 82
--Join tables as required and retrive PresciptionId, DiagnosisId, PrescriptionDate,
MedicineId and Dosage

--EXERCISE # 83
--Retrive PresciptionId, DiagnosisId, PrescriptionDate, MedicineId, Dosage and
Medicine Name

--EXERCISE # 84
-- Get the MRN, Full Name and Number of times each Patient is Diagnosed
--EXERCISE # 85
--Get Full Name and number of times every Doctor Diagnosed Patients

--EXERCISE # 86
--Patient diagnosis and prescribed Medicine Information
--MRN, Patient Full Name, Medicine Name, Prescibed Date and Doctor's Full Name

/*
OR

SELECT DG.mrn [MRN], CONCAT(P.pFName,' ',P.pLName) [Pateint Full Name],


M.brandName [Medicine Name], PR.prescriptionDate,
CONCAT(E.empFName,' ',E.empLName) [Doctor Full Name]
FROM Doctor DR JOIN Diagnosis DG ON DR.docId = DG.docId JOIN Employee E ON DR.empId
= E.empId JOIN
Patient P ON DG.mrn = P.mrn JOIN Prescription PR ON DG.diagnosisNo =
PR.diagnosisNo JOIN
MedicinePrescribed MP ON PR.prescriptionId = MP.prescriptionId JOIN
Medicine M ON MP.mId = M.mId

*/

/********** Some Join Exercises ***************

Write Queries for the following

1- Get Patients' information: MRN, Patient Full Name, and Diagnosed Date of
those diagnosed for disease with dId = 3
(Use filter in Where clause in addition to Joining tables Patient and
Diagnosis)

SELECT P.mrn, CONCAT(P.pFName,' ',P.pLName) AS [PATIENT


NAME],D.diagDate
FROM PATIENT AS P JOIN DIAGNOSIS AS D ON P.MRN = D.MRN
WHERE D.DID=3

2- Get the Employee Id, Full Name and Specializations for All Doctors

SELECT CONCAT(E.empFName,' ',E.empLName) AS [EMPLOYEE NAME],


E.empId, D.Specialization
FROM Employee AS E JOIN Doctor AS D on e.empId=D.empId

3- Get Disease Ids (dId) and the number of times Patients are diagnosed for
those diseases
(Use only Diagnosis table for this)
- Can you put in the order of (highest to lowest) based on the
number of times people diagnosed for the disease?
- Can you get the top most prevalent disease?
SELECT did, count(did)
FROM Diagnosis
GROUP BY did
ORDER BY count(did)

SELECT TOP (2) did, count(did)


FROM Diagnosis
GROUP BY did
ORDER BY count(did) DESC

4- Get Medicines (mId) and the number of times they are prescribed.
(Use only the MedicinePrescribed table)
- Also get the mId of medicine that is Prescribed the most

SELECT mId, count(mId)


FROM MedicinePrescribed
GROUP BY mId
ORDER BY count(mId)

--Medicine that is prescribed the most


SELECT TOP (2) mId, count(mId)
FROM MedicinePrescribed
GROUP BY mId
ORDER BY count(mId) desc

5- Can you add the name of the medicines the above query (question 4)?
(Join MedicinePrescribed and Medicine tables for this)

SELECT MP.mId, count(MP.mId), m.BrandName, M.genericName


FROM MedicinePrescribed AS MP JOIN Medicine as M ON MP.mId=M.mId
GROUP BY MP.mId,m.BrandName, M.genericName
ORDER BY count(MP.mId)

6- Alter the table PharmacyPersonel and Add a column ppId - which is a


primary key. You may use INT as a data type

ALTER TABLE PharmacyPersonel ADD ppId INT PRIMARY KEY (ppId) NOT
NULL

7- Create one table called MedicineDispense with the following properties


MedicineDispense(
dispenseNo - pk,
presciptionId and mId - together fk
dispensedDate - defaults to today
ppId - foreign key referencing the ppId
of PharmacyPersonnel table
)

CREATE TABLE MedicineDispense


(
dispenseNo INT NOT NULL,
prescriptionId INT NOT NULL,
mId SMALLINT NOT NULL,
dispensedDate DATE DEFAULT GETDATE(),
ppId INT NOT NULL,
CONSTRAINT PK_MedicineDispense_dispenseNo PRIMARY KEY
(dispenseNo),
CONSTRAINT FK_MedicineDispense_presciptionId_mId FOREIGN KEY
([prescriptionId],mId) REFERENCES MedicinePrescribed([prescriptionId],mId),
-- CONSTRAINT DEF_MedicineDispense_dispensedDate DEFAULT GETDATE()
for dispensedDate,
CONSTRAINT FK_MedicineDispense_ppId FOREIGN KEY (ppId)
REFERENCES PharmacyPersonel(ppId)
)

8- Add four Pharmacy Personnels (add four rows of data to the


PharmacyPersonnel table) - Remember PharmacyPersonnel are Employees
and every row you insert into the PharmacyPersonnel table should each
reference one Employee from Employee table

INSERT INTO PharmacyPersonel (empId,


pharmacistLisenceNo,licenceDate, PCATTestResult, level, ppId)
VALUES ('EMP02','GP-003','2012-02-06', 86, 'Out Patient',
1),
('EMP06','HP-012','2015-11-12', 72, 'In
Patient',2),
('EMP08','CP-073','2014-04-13', 93, 'Store
Manager',3),
('EMP10','GP-082', '2017-06-19', 67, 'Duty
Manager',4)

9- Add six MedicineDispense data

INSERT INTO MedicineDispense (dispenseNo, prescriptionId, mId,


dispensedDate, ppId)
VALUES (1,10,3,'2018-03-11',4),
(2,11,1,'2017-09-21',3),
(3,12,5,'2016-08-26',2),
(4,13,4,'2015-04-04',1),
(5,17,3,'2014-03-23',2),
(6,18,4,'2017-09-28',4)

*/

/*
SET OPERATIONS :
-UNION
-UNION ALL
-INTERSECT
-EXCEPT
*/

-- Set Operations on Result Sets


-- To Exemplify this in more detail, let's create below two tables

--CREATE TABLE HotelCust


--(
-- fName VARCHAR(20),
-- lName VARCHAR(20),
-- SSN CHAR(11),
-- DoB DATE
--);
--GO

--CREATE TABLE RentalCust


--(
-- firstName VARCHAR(20),
-- lastName VARCHAR(20),
-- social CHAR(11),
-- DoB DATE,
-- phoneNo CHAR(12)
--);
--GO

--INSERT INTO HotelCust


-- VALUES ('Dennis', 'Gogo', '123-45-6789', '2000-01-01'),
-- ('Belew', 'Haile', '210-45-6789', '1980-09-10'),
-- ('Nathan', 'Kasu', '302-45-6700', '1989-02-01'),
-- ('Kumar', 'Sachet', '318-45-3489', '1987-09-20'),
-- ('Mahder', 'Nega', '123-02-0089', '2002-01-05'),
-- ('Fiker', 'Johnson', '255-22-6033', '1978-05-10'),
-- ('Alemu', 'Tesema', '240-29-6035', '1982-05-16')

--INSERT INTO RentalCust


-- VALUES ('Ujulu', 'Obang', '000-48-6789', '2001-01-01','908-234-0987'),
-- ('Belew', 'Haile', '210-45-6789', '1980-09-10', '571-098-2312'),
-- ('Janet', 'Caleb', '903-00-4700', '1977-02-01', '204-123-0987'),
-- ('Kumar', 'Sachet', '318-45-3489', '1987-09-20', '555-666-7788'),
-- ('Mahder', 'Nega', '123-02-0089', '2002-01-05', '301-678-9087'),
-- ('John', 'Miller', '792-02-0789', '2005-10-25', '436-678-4567')

--To use UNION, the two tables must be UNION compatable


--EXAMPLE : Execute the following and explain the result,

--EXERCISE # 85
--Correct the above code and use 'UNION' operator to get the list of all customers
in HotelCustomrs and RentalCustomer

--EXERCISE # 86
--Use UNION ALL operator instead of UNION and explain the differece on the
result/output

--EXERCISE # 87
--Get list of customers in both Hotel and Rental Customers ( INTERSECT )

--EXERCISE # 88
--Get list of customers who are Hotel Customers but not Rental ( EXCEPT )

--EXERCISE # 89
--Get list of customers who are Rental Customers but not Hotel (EXCEPT )

/********************* STORED PROCEDURES **************************************

- STORED PROCEDURES (Procedure or Proc for short) are named database


- Are collections of TSQL statement stored in a database
- Can return results, manipulate data, and perform adminstrative actions on
server
- Stored procedures can include
- Insert / Update / Delete
- objects that encapsualte T-SQL Code (DDL, DML, DQL, DCL)
- Can be called with EXECUTE (EXEC) to run the encapsulated code
- Can accept parameters
- Used as interface layer between a database and application.

- Used for retrival / insertion / updating and deleting with complex


validation
: Views and Table Valued Functions are used for simple retrival

SYNTAX :
CREATE PROC <proc name>
[optional Parameter list]
AS
<t-sql code>

GO;

*/

--NOTE : use 'usp' as prefix for new procedures, to mean ' User created Stored
Procedure'

--EXAMPLE # 01
--Write a code that displays the list of patients and the dates they were diagnosed

--EXAMPLE # 02
--Customize the above code to creates a stored proc to gets the same result

--EXAMPLE # 03
--Execute the newly created stored procedure, using EXEC
--EXAMPLE # 04
--Modify the above procedure disply patients that was diagnosed in the year 2018

--EXAMPLE # 05
--Drop the procedure created in the above example

--EXAMPLE # 06 [ Procedure with parameter/s ]


--Create a proc that returns Doctors who diagnosed Patients in a given year

--EXAMPLE # 07 [ Procedure with DEFAULT values for parameter/s]


--Create a proc that returns Doctors who diagnosed Patients in a given year. The
same procedure
--will display a message 'Diagnosis Year Missing' if the year is not given as an
input.
--NOTE : If no specific year is entered, NULL is a default value for the parameter

--EXERCISE # 01
--Create a stored procedure that returns the the average salaries for each type of
employees.
--NOTE : use 'usp' as prefix for new procedures, to mean ' user created stored
procedure'

--It is also possible to use 'PROC' instead of 'PROCEDURE',

--It is also possible to use 'EXEC' instead of 'EXECUTE',

--EXERCISE # 02
--Create a stored procedure to get list of employees earning less than the average
salary of
--all employees
--NOTE : use 'usp' as prefix for new procedures, to mean ' user created stored
procedure'

--EXERCISE # 03
--Create a procedure that returns list of Contractors that earn less than average
salary of Principals
--EXERCISE # 04 (*)
--Create a proc that returns Doctors who diagnosed Patients in a year 2017
--NOTE : (1) The result must include DocId, Full Name, Specialization, Email
Address and DiagnosisDate

--EXERCISE # 05 (*)
--Create a stored proc that returns list of patients diagnosed by a given doctor.

--EXERCISE # 06 (*)
--Create a stored procedure that returns the average salary of Employees with a
given empType

--EXERCISE # 07 (*)
--Create a stored Proc that returns the number of diagnosis each doctor made in a
--given month of the year -> pass both month and year as integer values

--Putting the parameters in correct order when the procedure is defined


--Sequence of the parmeters matter

--Assigning the parameters when the procedure is called,


--Sequene of the parameters does't matter

/*

USING STORED PROCEDURES FOR DML

Stored procs are mainly used to perform DML on tables or views


Stored Procs to insert data into a table

*/

--EXAMPLE # 08
--Create a proc that is used to insert data into the Disease table
--to insert new record

--to remove newly inserted record

--to delete the procedure

--EXERCISE # 09
--Create a procedure to insert data into Doctors table,

--Confirm for the insertion of new record using SELECT statement

--EXERCISE # 10
--Create a stored Proc to deletes a record from RentalCust table with a given SSN

--EXERCISE # 11
--Create the stored procedure that delete a record of a customer in HotelCust table
for a given SSN
--The procedure must display 'invalid SSN' if the given ssn is not found in the
table

--EXERCISE # 12
--Write a stored procedure to delete a record from RentalCust for a given SSN. If
the SSN is not found
--the procedure deletes the entire rows in the table.
--NOTE : First take backup for Employee table before performing this task.

--EXERCISE # 13
--Write a code that displays the list of customers with the middle two numbers of
their SS is 45

--EXERCISE # 14
--Create a Proc that Deletes record/s from RentalCustomer table, by accepting ssn
as a parameter.
--The deletion can only happen if the middle two numbers of SSN is 45

-- Now test the sp


--EXERCISE # 15
--Create a procedure that takes two numeric characters, and delete row/s from
RentalCust table
--if the middle two characters of the customer/s socal# are same as the passed
characters

--EXERCISE # 16
--STORED PROCEDURES to update a table
--Create an stored procedure that updates the phone Number of a rental customer,
for a given customer
--Note : The procesure must take two parameters social and new phone number

--EXERCISE # 17
--Create a stored procedure that takes backup for RentalCust table into
RentalCust_Archive table
--Note : RentalCustArchive table must be first created.

--EXERCISE # 18
--Create a stored procedure that takes backup for HotelCust table into
HotelCustArchive table
--Note : Use 'EXECUTE' command to automatically create and populate
HotelCustArchive table.

--Exercise - 17
--Recreate the above stored proc such that, it shouldn't delete (purge the data)
before making
--sure the data is copied. Hint: use conditions (IF...ELSE) and TRY ... CATCH
clauses

-- A simpler version of the above Stored Proc - with no dynamic date value
appending to table name

/*
--************************************ VIEWS
*****************************************************

VIEWS
- Quite simply VIEW is saved query, or a copy of stored query, stored
on the server
- Is Virtual Table - that encapsulate SELECT queriey/es
**** - It doesn't store data persistantly, but creates a Virtual table.
- Can be used as a source for queries in much the same way as tables
themselves
: Can also be used to Join with tables
- Replaces commonly run query/ies
- Can't accept input parameters (Unlike Table Valued Functions (TVFs))

- Components
: A name
: Underlaying query

- Advantages
- Hides the complexity of queries, (large size of codding)
- Used as a mechanism to implement ROW and COLUMN level security
- Can be used to present aggregated data and hide detail data

- SYNTAX
: To create a view:

CREATE VIEW <view name>


AS
<Select statement>
GO

: To modify

ALTER VIEW <view name>


AS
<Select statement>
GO

: To drop
DROP VIEW statement
AS
<Select statement>
GO

At view creation, 'GO' acts as delimiter to form a batch.

To display the code, use 'sp_helptext' for a stored procedure


Syntax : 'sp_helptext < view_name >

*/

--EXAMPLE - View # 01
--Write a code that displays patient's MRN, Full Name, Address, Disease Id and
Disease Name

--EXAMPLE - View # 02
--Create simple view named vw_PatientDiagnosed using the above code.
--EXAMPLE - View # 03
--Check the result of vw_PatientDiagnosed by SELECT statement

--EXAMPLE - View # 04
--Use vw_PatientDiagnosed and retrieve only the patients that came from MD
--Note : It is possible to filter Views based on a criteria, similar with tables

--EXAMPLE - View # 05
--Modify vw_PatientDiagnosed so that it returns the patients diagnosed in year 2017

--EXAMPLE - View # 06
--Check the result of modified vw_PatientDiagnosed by SELECT statement

--EXAMPLE - View # 07
--Use sp_helptext to view the code for vw_PatientDiagnosed
--sp_helptext vw_PatientDiagnosed

--EXAMPLE - View # 08
--Drop vw_PatientDiagnosed

--EXERCISE - View # 01
--Create a view that returns Employees that live in state of Maryland, (Employee
empId, FullName, DOB)

--EXERCISE - View # 02
--Create view that displays mId, Medicine ID and the number of times each medicine
was
--prescribed.

--EXERCISE - View # 03
--Join vw_MedicinePrescribed with Medicine table and get mId, brandName,
genericName and
--number of times each medicine was prescribed

--EXERCISE - View # 04
--Create a view that displays all details of a patient along with his/her diagnosis
details

--EXERCISE - View # 05
--Use the view created for 'EXERCISE - View # 04' to get the full detail of the
doctors

--EXERCISE - View # 06 (*)


--Create the view that returns Contract employees only, empType='C'

--EXERCISE - View # 07 (*)


--Create the view that returns list of female employees that earn more
--than the average salary of male employees

--EXERCISE - View # 08 (*)


--Create the view that returns list of employees that are not doctors

--EXERCISE - View # 09 (*)


--Create the view that returns list of employees that are not pharmacy personel

--EXERCISE - View # 10 (*)


--Create the view that returns empid, full name, dob and ssn of doctors and
pharmacy personels

--EXERCISE - View # 11 (*)


--Create the view that returns list of medicines that are not never prescribed.

--EXERCISE - View # 12 (*)


--Create the view that returns list of patients that are not diagnosed for a
disease 'Cholera'

--EXERCISE - View # 13 (*)


--Create the view that returns list of employees that earn less than employees
averge salary

--EXERCISE - View # 14 (*)


--Create simple view on Disease table vw_Disease that dispaly entire data
--EXERCISE - View # 15 (*)
--Create view that returns list of doctors that had never done any diagnossis.

--EXERCISE - View # 16 (*)


--Use view, vw_Disease, to insert one instance/record in Disease table

--EXERCISE - View # 17 (*)


--Use view, vw_Disease, to delete a record intered on previous exercise.

--EXERCISE - View # 18 (*)


--Create simple view on Medicine table vw_Medicine that dispaly entire data

--EXERCISE - View # 19 (*)


--Insert data into the Medicine table using vw_Medicine

-- INSERT INTO vw_Medicine VALUES (13, 'Asprine', 'No name', 2000, 'Pain
killer','2024-02-09', 0.35)

/*
NOTE : Data insertion by views on more than one tables (joined) is not supported
: Data insertion on joined tables is supported by triggers
*/

--EXERCISE - View # 20 (*)


--Create a view, vw_PatientAndDiagnosis, by joining patient and diagnosis tables
and
--try to insert data into vw_PatientDiagnosis view and explain your observation

/************************ USER DEFINED FUNCTIONS, UDFs


**********************************************

User Defined Functions, UDFs

- Can return a scalar value (single value), inline table-valued OR


multi table-valued

User Defined Functions, UDFs


: Is compiled and executed everytime/whenever it is called.
: The function must return a value
*** : Function allows only SELECT statement in it.
*** : Function can be embedded in a SELECT statement.
*** : Functins can be used in the SQL statements anywhere in the
WHERE/HAVING/SELECT sections

- Difference with stored procedures,

Stored Procedure, SPs


: Are pre-compiled objects saved, in database, which gets
executed whenever it is called.
: Returing a value is optional, can return zero or n values.
*** : Allows SELECT as well as DML(INSERT/UPDATE/DELETE) statement
*** : Cannot be utilized in a SELECT statement
*** : Cannot be used in the SQL statements anywhere in the
WHERE/HAVING/SELECT sections

- Types of User Defined Functions :


- Scalar Functions
- Inline Table-Valued Functins, TVFs
- Multi-Statement Table-Valued Functions

- Scalar Fuctions
- May or may not have parameter, but always return SINGLE (Scalar)
value
- Return value can be of any data type, except text, ntext, image,
cusror and timestamp.
- Example :
- System functions are scalar functions

- SYNTAX:

To create (Scalar Function)


CREATE FUNCTION function_name (@Para1 DataType, @Para2
DataType........)
RETURNS Return_Data_Type --scalar
AS
BEGIN
<statements> --Function Body
RETURN <value>
END

To create (Table Valued Function)


CREATE FUNCTION function_name (@Para1 DataType, @Para2
DataType........)
RETURNS TABLE -- table valued
AS
RETURN
(
<statements>
)

TO modify/alter
ALTER FUNCTION function_name

TO drop/delete
DROP FUNCTION function_name
*/

--EXAMPLE : UDF # 01
--Create a scalar valued function that returns the total number of Employees
--Note : UDF without parameter

--Now call the function to get the result


--While calling a udf, don't forget the precede it with the name of the schema that
contains it

--EXAMPLE : UDF # 02
--Create a udf that returns the average salary of a given employee type
--Note : UDF with parameter

--Now call the function with different empTypes

--EXAMPLE : TVF # 01
--Create a user defined function, tvf_GetEmpTypeAndAVGSalary, that returns empType
and their
--corresponding Average Salaries. ( Creating UDF that returns a table )

--Now call your function to get the result

--EXAMPLE - TVF # 02
--Create TVF, tvf_TopHighlyPayedEmployees, that can retrieve the full name and dob
of the
--top 'x' number of highly paied employees.

--EXERCISE : UDF # 01
--Get the list of employees that earn less than the average salary of their own
employee type.
--Note : Use udf, that takes empType and returns Salary average, within WHERE
clause to define
--the criteria.

--EXERCISE : UDF # 02
--Use the tdf, tvf_GetEmpTypeAndAVGSalary, created on 'EXAMPLE : TVF # 01' and join
with
--Employee table to get Employees that earn less than the average salaries of their
corresponding types

--EXERCISE - UDF # 03
--Disply the full name, gender, dob and AGE of all employees.
--NOTE : Create udf that returns AGE by taking DoB as an input parameter
--EXERCISE - UDF # 04
--Disply list of Doctor's id along with the number of patients each one had
diagnosed.
--(use a function to determine number of patients diagnosed )

--EXERCISE - UDF # 05 (*)


--Edit the above code, 'EXERCISE - UDF # 04' to display only the doctors that
diagnosed
--more than 2 patients.

--EXERCISE - UDF # 06 (*)


--Disply the list of states along with the number of employees living in.
--(use a function to calculate the number of employees )

--Method (1)

--Method (2)

--EXERCISE - UDF # 07 (*)


--Edit the above code, 'EXERCISE - UDF # 07' to display a state with highest number
--of employees.

--EXERCISE - UDF # 08 (*)


--Disply the list of medicines along with the number of time it was prescribed. Use
a function
--to deterime the number of times each medicine was prescribed.

--Method (1)

--Method (2)

--EXERCISE - UDF # 09 (*)


--Modify the code for 'EXERCISE - UDF # 08' to include the name and brand of
medicine as an output.

--Using Method(1)

--Using Method (2)

--EXERCISE - UDF # 10 (*)


--Create a function, UDF, that perform addition, subtraction, multiplication and
divisioin.

--EXERCISE - TVF # 01
--Create TVF that can retrive the employee id, full name and dob of the ones that
earn
--more than a given salary.

--EXERCISE - TVF # 02
--Create TVF that can retrive the number of times each medicine was prescribed.

--Include BrandName and GenericName of each medicine

--EXERCISE - TVF # 03
--Create TVF that can return a list of employees with a given gender.

--EXERCISE - TVF # 04
--Create TVF that can return full name of patients that are diagnosed with a given
disease.
--Note : The diseased is identified by name only.

/******************* COMMON TABLE EXPRESSIONS (CTEs)


***************************************

COMMON TABLE EXPRESSIONS (CTEs)

- It is a TEMPORARY result set, that can be referenced within a SELECT,


INSERT,
UPDATE or DELETE statements that immediately follows the CTE.
- Is a named table expressions defined in a query
- Provides a mechanism for defining a subquery that may then be used
elsewhere in a query
***** - Should be used after the statement that created it
- Defined at the beginning of a query and may be refernced multiple
times in the outer query
- Defined in 'WITH clause'
- Does not take parameter (unlike views, functions and stored
procedures)
- Does not reside in database (unlike views, functions and stored
procedures)
Syntax:

WITH <CTE_name> [Optional Columns list corresponding to the values


returned from inner select]
AS (
<Select Statement>
)
...
...
...
< SELECT query where the CTE is utilized >

*/

--EXAMPLE - CTE # 01
--Create a CTE that returns medicines and number of times they are prescribed (mId,
NumberOfPrescriptions)
--Then join the created CTE with Medicine table to get the name and number of
prescription of the medecines

--EXAMPLE - CTE # 02
--Create CTE that returns the average salaries of each type of employees

--EXERCISE - CTE # 01
--Modify the above code to sort the output by empType in descending order.

--EXERCISE - CTE # 02
--Create CTE to display PrescriptionId, DiagnossisNo, Prescription Date for each
patient. Then use
--the created CTE to retrive the dossage and number of allowed refills.

--EXERCISE - CTE # 03 (*)


--Create CTE to display the list of patients. The result must include mrn, full
name, gender, dob and ssn.

--EXERCISE - CTE # 04 (*)


--Modify the above script to make use of the CTE to display the name of a disease
--each patient is diagnosed

--EXERCISE - CTE # 05 (*)


--Create CTE to display DiagnossisNo, DiagnossisDate and Disease Type of all
Diagnossis made. Later use the CTE
--to include the rank of the specialization and rank of the doctor.

--EXERCISE - CTE # 06 (*)


--Modify the above code, to incude doctor's full name and dob.
--EXERCISE - CTE # 07 (*)
--Create CTE that returns the average salaries of each type of employees. Then use
the same CTE
--to display the list of employees that earn less than their respective employee
type average salaries

--EXERCISE - CTE # 08 (*)


--Create CTE that calculates the average salaries for each type of employees

--EXERCISE - CTE # 09 (*)


--Use the CTE created for 'EXERCISE - CTE # 09' and provide the list of employees
that earn less more than
--the average salary of their own gender.

--EXERCISE - CTE # 10 (*)


--Create CTE that calculates the average salaries for female employees. Use the
created CTE to display
--list of male employees that earn less than the average salary of female
employees.

/********************************* TRIGGERS
***********************************************

TRIGGERS -
- Are a special type of stored procedures that are fired/executed
automatically in response
to a triggering action
- Helps to get/capture audit information
- Like stored procedures, views or functions, triggers encapsulate code.
- Triggers get fired (and run) by themselves only when the event for which
they are
created for occurs, i.e. We do not call and run triggers, they get
fired/run
by by their own

Types of triggers
- DML triggers
: Fires in response to DML events (Insert/Delete/Update)
- DDL triggers
: Fires in response to DDL events (Create/Alter/Drop)
- login triggers
: Fires in response to login events

DML Triggers
There are two types of DML Triggers: AFTER/FOR and INSTEAD OF, and
there are
three DML events (INSERT, DELETE and UPDATE) under each type -
FOR/AFTER INSERT
DELETE
UPDATE

INSTEAD OF INSERT
DELETE
UPDATE

Syntax:
Whenever a trigger is created, it must be created for a given table,
and for a
specific event,

CREATE TRIGGER <trigger name> -- name of the


trigger
ON <table name>
-- name of table
<FOR/AFTER | INSTEAD OF INSERT/DELETE/UPDATE> -- specific event
AS
BEGIN
<your t-sql statement>
END

Uses for triggers:


- Enforce business rules
- Validate input data
- Generate a unique value for a newly-inserted row in a different file.
- Write to other files for audit trail purposes
- Query from other files for cross-referencing purposes
- Access system functions
- Replicate data to different files to achieve data consistency

*/

--EXERCISE - TRIGGER # 01 (FOR/AFTER) UPDATE


--Create a trigger that displays a message 'Disease table is updated' when the
table gets updated

--First check the content dType for dId=5 before updating

--Update the table,

--Check the table after update,

--Drop/Delete a trigger

--EXERCISE - TRIGGER # 02 (FOR/AFTER INSERT)


--Create a trigger that displays a message 'New disease is inserted' when a new
record gets
--instered on disease table

--EXERCISE - TRIGGER # 03 (FOR/AFTER) DELETE


--Create a trigger that displays a message 'A record is deleted from HotelCust
table' when a new record gets
--deleted from HotelCust table

--EXERCISE - TRIGGER # 04 (INSTEAD OF INSERT)(*)


--Create a trigger that displays a message 'A new record was about to be inserted
into HotelCust table' when
--a new record was about to be inserted on HotelCust table

--EXERCISE - TRIGGER # 05 (INSTEAD OF UPDATE) (*)


--Create a trigger that displays a message 'A record was about to be UPDATED into
Medicine table' when
--a record was about to be updated on Medicine table

--EXERCISE - TRIGGER # 06 (INSTEAD OF DELETE) (*)


--Create a trigger that displays a message 'A record was about to be DELETED from
RentalCust table' when
--a record was about to be deleted on RentalCust table

/*
The use of 'inserted' table and 'deleted' table by triggers.

- DML trigger statements use two special tables: the deleted table and the
inserted tables.
- SQL Server automatically creates and manages these two tables.
- They are temporary, that only lasts within the life of trigger
- These two tables can be used to test the effects of certain data
modifications
and to set conditions for DML trigger actions.

- In DML triggers, the inserted and deleted tables are primarily used to
perform the following:
- Extend referential integrity between tables.
- Insert or update data in base tables underlying a view.
- Test for errors and take action based on the error.
- Find the difference between the state of a table before and after a
data
modification and take actions based on that difference.

**** - The deleted table stores copies of the affected rows during DELETE and
UPDATE statements.
*** - The inserted table stores copies of the affected rows during INSERT and
UPDATE statements.

*/

--EXERCISE - TRIGGER # 07 (Using 'inserted' table)


--Create a trigger that displays the inserted record on RentalCust table

--EXAMPLE - TRIGGER # 08 (Using 'deleted' table)

--EXAMPLE - TRIGGER # 09 (Using 'deleted' table)


--Create following audit table, that maintains/captures the records deleted/removed
from HotelCust
--and create a trigger that inititate data backup when a record is deleted from
HotelCust table
--Note : Use FOR/AFTER DELETE trigger as required.

--EXERCISE - TRIGGER # 10 (Using 'inserted' table)


--Create Audit table, RentalCustInsertAudit, that maintains/captures the records
inserted
--on RentalCust table. The audit table also capture the date the insertion took
place
--Note : Use FOR/AFTER INSERT trigger as required.

--EXERCISE - TRIGGER # 11 (AFTER INSERT TRIGGER, Application for Audit) (*)


--Create Audit table, Medicine_Insert_Audit, that maintains/captures the new mId,
BrandName,
--the person that made the entery, the date/time of data entery.
--Use system function 'SYSTEM_USER' to get login detail of the user that perform
data insertion

--Now create a trigger that automagically inserts data into the MedicineInsertAudit
table,
--whenever data inserted into Medicine table

--Test how the trigger works by inserting one row data to Medicine table

--EXERCISE - TRIGGER # 12 (AFTER DELETE TRIGGER, Application for Archive) (*)


--Create and use archieve table, Disease_Delete_Archive, that archieves the disease
information
--deleted from Disease table. The same table must also capture the time and the
person
--that does the delete.
--NOTE : Use system function SYSTEM_USER to return the system user.

--EXERCISE - TRIGGER # 13 (*)


--Create a trigger that displays the following kind of message when a record is
deleted from HotelCust table.
--Assume the record for 'Abebe' is deleted, the trigger should display
-- 'A record for Abebe is deleted from HotelCust table'

--EXERCISE - TRIGGER # 14 (AFTER UPDATE TRIGGER, Application for audit) (*)


--Create an After Update Trigger on Employee table that documents the old and new
salary information of
--an Employee and the date salary update was changed.
--First create EmployeePromotionTracker (empId, promoDate, oldSalary, newSalary)

--Now check the tigger by updating one employee salary


--First check the data in both tables

--EXERCISE - TRIGGER # 15 ( AFTER UPDATE )


--Create the following audit table, RentalCust_Update_Audit, and code a trigger
that
--can maintains/captures the updated record/s of RentalCust table.

--Assume both the fist name and DoB changed during update, The 'Message' column
should capture
--a customized statement as follows
-- 'First Name changed from 'Abebe' to 'Kebede', DoB changed from 'old DoB' to
'new DoB'

--Similarly the 'Message' column should be able to capture all the changes that
took place.

--EXERCISE - TRIGGER # 16 (*)


--Create Medicine_Audit table, with two columns having Integer with IDENDITY
function and description - nvarchar(500)
--data types. The table must insert a description for the changes made on Medicine
table during UPDATE

--EXERCISE - TRIGGER # 18 (After Delete Trigger ) (*)


--Create a trigger that archieve the list of Terminated/Deleted Employees.
--Problem analysis :
--The employee can be a Doctor, PharmacyPersonel or Just Employee. Since, Doctor
and
--PharmacyPersonnel tables depend on the Employee table, we need to first redfine
the foreign keys
--to allow employee delete - with cascading effect. Then the next challenge is,
deleting a Doctor
--also affecs the Diagnosis table, we should redefine the foreign key between
Doctor and Diagnosis
--table to allow the delete - with SET NULL effect

--Steps to follow,
--Step (1): Drop the Foreign Key Constraints from the Doctor, PharmacyPersonel,
Diagnosis, and MedicineDispense tables
-- and redefine FK constraints for all child tables
--Step (2): Create the Employee_Terminated_Archive table
--Step (3): Create the trigger that inserts the deleted employee data into
Employee_Terminated_Archive

--Step (1): Drop the Foreign Key Constraints from the Doctor, PharmacyPersonel,
Diagnosis, and MedicineDispense tables
-- and redefine FK constraints for all child tables

--: Now redefine the Constraints

--Step 2: Create the Employee_Terminated_Archive table

--Step3: Create the trigger that inserts the deleted employee data into
Employee_Terminated_Archive table
--by checking the role of the employee

--Now test the trigger at work by deleting an Employee - employee data will be
archived, but
--the employee role wont be set as expected

--EXERCISE - TRIGGER # 19 (*)


--Modify the above trigger and archieve table to include the role of the employee
if he/she is Doctor
--or PharmacyPersonel, and the date the employee was terminated.

--Step3: Create the trigger that inserts the deleted employee data into
Employee_Terminated_Archive table by checking the role of the employee
--Now test the trigger at work by deleting an Employee - employee data will be
archived, but
--the employee role wont be set as expected

--EXAMPLE - TRIGGER (Instead of Delete Trigger )


--The above requirement can better be fulfilled within INSTEAD OF DELETE trigger as
follows:
--DROP TRIGGER trg_Instead_Of_Delete_Employee_Termination

--Now test deleting an employee that is a 1) Doctor 2) PharmacyPersonel and 3)any


other employee

--EXERCISE - TRIGGER # 20 ( Instead of Delete Trigger ) (*)


--Create an Instead of delete trigger on Diagnosis table, that simply prints a
warning 'You can't delete Diagnosis data!'

--EXERCISE - TRIGGER # 19 - TRIGGER # 06 ( AFTER UPDATE )


--Create the following audit table, RentalCust_Update_Audit, and code a trigger
that
--can maintains/captures the updated record/s of RentalCust table.

--EXERCISE - TRIGGER # 21 ( Using triggers to insert data into multiple tables )


--Inserting data into a view that is created from multiple base tables
--First create the view - e.g. a view on Doctor and Employee tables
( vw_DoctorEmployee )

-- There are times where we want to insert data into tables through views,
-- Assume that we hired a doctor (an employee) having all the employee and doctor
information;
-- for this we want to insert data into both tables through the view
vw_DoctorEmployee
-- But this will not go as intended, because of multiple base tables.... see below

--Above insert statement will error out as follows


--Error:
--Msg 4405, Level 16, State 1, Line 1763
--View or function 'vw_DoctorEmployee' is not updatable because the modification
affects multiple base tables.

--Now create an instead of insert trigger on the view vw_DoctorEmployee -> that
takes the data and inserts into
--the tables individually

-- Now retry the above insert statement

You might also like