Proj 1
Proj 1
Proj 1
Here we build and use a database for a hypothetical Health Record Management
System, HRMS
*/
USE master;
GO
USE HRMSDB;
GO
-- 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 ] ]
--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
--EXERCISE # 02
--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.
--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 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.
--EXERCISE # 07
--Write a code to display employee's Full Address, and Phone Number
Select strAddress + ' '+'Apt#' + apt + ' '+ city +',' + ' ' + [state]+ ' ' +
zipCode as EmpFullAdress, 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#',' ', apt,' ',city,',',' ', [state], ' ',
zipCode) as EmpFullAdress, 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 left(employedDate,4)
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
--EXERCISE # 10
--Write the code to display the 10% rise on the price of each Medicine, use
appropriate column alias for comoputed column
--EXERCISE # 11
--Modify the above code to include the new price column with the name 'New Price'
--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%
--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
--EXERCISE # 13
--Assign the appropriate aliases for columns displayed on previous exercise.
/*
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
--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 [First Name] 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
*/
--EXAMPLE :
--Simple CASE
/*
First
ALTER TABLE Disease
DROP COLUMN dCategory
*/
SELECT * FROM Disease
--EXAMPLE :
--Searched CASE
--EXERCISE # 14
--Use simple CASE to list the brand names of medecines available as per Medecine Id
Select brandName,mId,
case mId
When '1' then 'Xaleto'
When '2' then 'Eliquis'
When '3' then 'Tran.Acid'
When '4' then 'Fosamax'
when '5' then 'Hexalen Capsules'
when '6' then 'Prozac'
when '7' then 'Glucofage'
when '8' then 'Advil'
when '9' then 'Amoxy'
else 'No Brand Name'
End As MedicinAvailable
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, GenericName,unitPrice,
case when unitPrice < '15' then 'Cheap'
When unitPrice < '45' then 'Moderate'
else 'Expensive' end as CategoryofPrice
From Medicine
-- Display MRN, Full Name and Gender (as Female and Male) of all Patients -- use
case statement for gender
/*
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]
*/
Select salary
From Employee
where salary < 75000.00
Select*
From Patient
Where [state] not in ('DC','MD', 'VA'))
Select*
From Patient
Where [state] = 'FL' or [state] = 'VA' or [state] = 'TX'
Select*
From Patient
Where gender = 'F' and [State] in ('FL','VA', 'TX')
-- Also order by last name - and return the names as lastname, firstname
Select*
from Employee
order by empLName asc
--EXERCISE # 16
--Write a code to retrive details of Patients in assending order of last names
Select*
From Patient
order by pLName asc
--EXERCISE # 17
--Write a code to retrive details of Employees in descending order of DoB
--Note : Use column alias on ORDER BY clause
Select*
From Employee
order by DoB desc
*/
--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.
/*
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>
*/
--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
Select*
From Employee
Where empType = 'c'
--EXAMPLE :
--Find below a code to get Employee information (across all columns) - for
Contract and Associate
Select*
From Employee
Where empType = 'A'
--EXERCISE # 19
--Find the list of employees with salary above 90,000
Select*
From Employee
where salary > 90000
--EXERCISE # 20
--Find the list of employees with salary range betwen 85,000 to 90,000 inclusive
Select*
From Employee
Where salary between 85000 and 90000
--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'
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 = '1980-01-01' and DoB = '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 = 'Silver Spring'
--EXERCISE # 25
--Write a code retrive the information of contractor Employees with salary less
than 75000.
Select*
From Employee
where empType = 'c' and salary < 75000
--EXERCISE # 26
--Write a code to retrive list of medicines with price below 30 USD.
Select*
From Medicine
Where unitPrice < 30
--EXERCISE # 27
--Write a code to retrive patients that live in Miami and Seattle
Select*
From Patient
Where city = 'Miami' or city = 'Seattle'
--EXERCISE # 28
--Write a code to retrive patients that are not living in Silver Spring
Select*
From Patient
Where city not in ('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 )
- RIGHT
- To extract a substring from a string, starting from the right-most
character.
- SYNTAX
RIGHT( string or string_exp, number_of_characters )
- 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
-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 )
https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/string-
functions?view=sql-server-2017
*/
--EXERCISE # 29
--Write a code to display full name for employees
--EXERCISE : 30
--Get the last four digists of SSN of all Employees together with their id and full
name
-- 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'
Select Right(SSN, 4), empId, DoB, CONCAT(empFName, ' ', empLName) as FullName
From Employee
Where Right(SSN,4) = '3456' and DoB = '1980-09-07'
--EXERCISE # 31
--Write a code to retrive the full name and area code of their phone number, use
Employee table
--EXERCISE # 32
--Write a code to retrive the full name and area code of their phone number,
(without a bracket). use Employee table
--EXAMPLE # 33
--Run the following codes and explain the result with the purpose of CHARINDEX
function
SELECT CHARINDEX('O', 'I love SQL')
--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']
--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
where CHARINDEX('%',strAddress) =
--EXAMPLE :
--Run the following code and explain the result with the purpose of LEN function
SELECT LEN('I love SQL')
It gives (10)the number of the letters 'I love SQL' including the space in between
the words.
--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 CHARINDEX('P', empFName) = 1
--EXERCISE # 39
--Get the list of employees with 2nd letter of their frst name is 'a'
Select*
From Employee
Where CHARINDEX('a', empFName) = 2
--EXERCISE # 40
--Get full name of employees with earning more than 75000. (Add salary information
to result set)
Select*
From Employee
Where salary > 75000
--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 RIGHT(email, (len(email)-CHARINDEX('@',email))) = 'yahoo.com'
--EXERCISE # 42
--Get Employees who have yahoo email account
--NOTE : Use RIGHT string function.
Select*
From Employee
where RIGHT(email, (len(email)-CHARINDEX('@',email))) = 'yahoo.com'
--EXERCISE # 43
--Get Employees who have yahoo email account
--NOTE : The code must checke only 'yahoo' to retrive the entire employees with
yahoo account
Select*
From Employee
where SUBSTRING(email,(CHARINDEX('@', email))+1,5)= 'yahoo'
--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
--EXERCISE # 45
--Get total number of Employees
Select count(empId)as TotalNumberOfEmp
From Employee
--EXERCISE # 46
--Get number of Employees not from Maryland
Select count(empId)
From Employee
Where [state] not in ('MD')
--OR
--EXERCISE # 47
--Get the number of Principal Employees, with emptype = 'P')
Select count(empId)
From Employee
where empType ='p'
--EXERCISE # 48
--Get the Minimum salary
Select min(Salary)
From Employee
--EXERCISE # 49
--Modify the above code to include the Minimum, Maximum, Average and Sum of the
Salaries of all employees
Select min(salary) as MinimumSalary,
max(salary) as MaximumSalary,
AVG(salary) as AvgSalary,
Sum(salary) as SumofSalary
From Employee
--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?
Select empType, AVG(salary) as AverageSalary
From Employee
Group by empType
--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 # 56
--Note : The answer for the this exercise will be used as subquery to the next
question )
--Get the average salary of all employees
Select AVG(salary)
From Employee
--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
Select*
From Employee
where salary < (select AVG(salary) from Employee)
-- 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
Select*
From Employee E1
where Department = 'AK12' and salary < (select AVG(salary) from Employee E2 where
E1.department = e2.department)
--- Q2: Get Employees working in department 'HN02' and earning less than or equal
to the departmental average salary
Select*
From Employee E1
where Department = 'HN02' and salary <= (select AVG(salary) from Employee E2 where
E1.department = E2.department)
--- Q3: Get Employees working in department 'KB10' and earning less than or equal
to the departmental average salary
Select*
From Employee E1
where Department = 'KB10' and salary <= (select AVG(salary) from Employee E2 where
E1.department = E2.department)
--- Q4: Get Employees working in department 'VL20' and earning less than or equal
to the departmental average salary
Select*
From Employee E1
where Department = 'VL20' and salary <=(Select avg(salary) from Employee E2 where
E1.department = E2.department)
-- The question is to create one query that returns all the above together
Select*
From Employee E1
Where Department in ('AK12', 'HN02','KB10','Vl20') and salary <=(select
AVG(salary)from Employee E2 where E1.department = E2.department)
--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
Select*
From Employee
where salary<(select avg(salary) from employee where empType = 'A')
--EXERCISE # 59
--Get Principal Employees earning less than the average of Contractors
Select*
From Employee
Where empType = 'P'and salary < (select AVG(salary) from Employee where empType =
'C')
--EXERCISE # 60
--Get Principal Employees earning less than or equal to the average salary of
Pricipal Employees
Select*
From Employee
Where empType = 'P' and salary <= (Select avg(salary) from Employee where empType =
'P')
--EXERCISE # 61
--Get Contractors earning less than or equal to the average salary of Contractors
Select*
From Employee
Where empType = 'C' and salary <= (Select avg(salary) from Employee where empType =
'C')
--EXERCISE # 62
--Get Associate Employees earning less than or equal to the average salary of
Associate Employees
Select*
From Employee
where empType = 'A' and salary <= (select avg(salary) from Employee where empType =
'A')
--EXERCISE # 63
--Get Managers earning less than or equal to the average salary of Managers
Select*
from Employee
Where empType = 'M' and salary <= (select avg(salary) from Employee where empType =
'M')
--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
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
Select*
from Employee E1
where salary <= (select avg(salary) from Employee E2 where E1.gender = E2.gender)
--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
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
/*
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
- 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
*/
--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
--Execute the following to get LEFT OUTER JOIN b/n T1 and T2 with condition columns
'A'
--on both tables have same value
Select T1.A, B, C
from T1
left outer join T2 on T1.A = T2.A
--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
Select T2.A, B, C
From T1
right outer join T2 on T1.A = T2.A
--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
Select T1.A, B, C
From T1
Full outer join T2 on t1.A = t2.A
--EXERCISE # 72
--Get the CROSS JOIN of Patient and Diagnosis tables
Select*
From Patient
cross join Diagnosis
--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
Select*
From Patient P
cross join Diagnosis D
where p.mrn = D.mrn
--EXERCISE # 74
-- Retrive MRN, Full Name, Diagnosed Date, Disease Id, Result and Doctor Id for
Patient, MRN = 'PA002'
Select P.mrn, Concat(P.pFName, ' ', pLName) as FullName, D.diagDate, D.dId,
D.diagResult
From Patient P
Join Diagnosis D on P.mrn = D.mrn
Where P.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
Select*
From Employee E
left join Doctor D on E.empId = D.empId
Where e.department not in ('HN02')
--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
select*
From Doctor D1
right join Diagnosis D2 on D1.docId = D2.docId
Where D1.docId not in (D2.docId)
--EXERCISE # 75
--Display the list of medicines that are prescribed by any of the doctor. (Use
RIGHT OUTER JOIN)
Select*
From Medicine M
right join MedicinePrescribed MD on m.mId = MD.mId
--EXERCISE # 76
--Display the list of medicines that which not prescribed by any of the doctors.
(Use RIGHT OUTER JOIN)
Select *
From Medicine M
right join MedicinePrescribed MD on M.mId = MD.mId
Where M.mId not in (MD.mid)
--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
Select Concat(e.empFName, ' ', e.empLName) as FullName
From Employee E
Join Doctor DR on E.empId = Dr.empId
join Diagnosis DG on DR.docId = DG.docId
Group by DG.docId
Order by count(DG.docID)
--EXERCISE # 86
--Patient diagnosis and prescribed Medicine Information
--MRN, Patient Full Name, Medicine Name, Prescibed Date and Doctor's Full Name
--OR
--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)
--2- Get the Employee Id, Full Name and Specializations for All Doctors
--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?
--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
--6- Alter the table PharmacyPersonel and Add a column ppId - which is a
primary key. You may use INT as a data type
/*
----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
-- )
*/
--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
/*
SET OPERATIONS :
-UNION
-UNION ALL
-INTERSECT
-EXCEPT
*/
--EXERCISE # 85
--Correct the above code and use 'UNION' operator to get the list of all customers
in HotelCustomrs and RentalCustomer
Select concat(fName, ' ', lName)as FullName
From HotelCust
Union
Select concat(firstName, ' ', lastName) as FullName
From RentalCust
--EXERCISE # 86
--Use UNION ALL operator instead of UNION and explain the differece on the
result/output
Select concat(fName, ' ', lName)as FullName
From HotelCust
Union
Select concat(firstName, ' ', lastName) as FullName
From RentalCust
There are a duplicate when use 'union all' operator.
--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 )
Select concat(fName,' ', lName) as FullName
From HotelCust
except
Select concat(firstName, ' ', lastName) as FullName
from RentalCust
--EXERCISE # 89
--Get list of customers who are Rental Customers but not Hotel (EXCEPT )
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
create proc ups_Patients
as
begin
Select mrn,diagDate
From Diagnosis
end
go
EXECUTE ups_Patients
GO
--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
execute ups_patients
--EXAMPLE # 04
--Modify the above procedure disply patients that was diagnosed in the year 2018
Alter Proc ups_Patients
as
begin
Select mrn, datepart(yy,diagDate)
from Diagnosis
where datepart(yy, diagDate) = 2018
End
go
execute ups_Patients
--EXAMPLE # 05
--Drop the procedure created in the above example
drop Proc ups_Patients
--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'
Create Proc usp_employee
as
begin
Select avg(salary), empType
From Employee
Group by empType
end
go
Execute usp_employee
--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
create proc usp_Contractors
as
begin
Select empId, concat(empFName, ' ', empLName) as FullName, salary
From Employee
where empType = 'C' and salary < (select AVG(salary) from Employee where
empType = 'P')
end
go
execute usp_Contractors
--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
execute Usp_DoctorDiag
--EXERCISE # 05 (*)
--Create a stored proc that returns list of patients diagnosed by a given doctor.
Alter proc usp_Patient
@docId Varchar(5)
as
begin
select P.mrn, concat(P.pFName, ' ', P.pLName) as FullName, D.docId
From Diagnosis D
join Patient P on D.mrn = P.mrn
Where @docId = docId
end
go
--EXERCISE # 06 (*)
--Create a stored procedure that returns the average salary of Employees with a
given empType
Create proc usp_AverageSalary
@empTyp char (1)
as
begin
select AVG(salary), empType
From Employee
where @emptyp = empType
group by empType
end
go
/*
*/
--EXAMPLE # 08
--Create a proc that is used to insert data into the Disease table
Execute usp_Disease
@dId = '7',
@dname = 'COVID-19',
@dcate = 'virus',
@dtype = 'Contageous'
Select*
from Disease
execute usp_Diseasedelete
--EXERCISE # 09
--Create a procedure to insert data into Doctors table,
Create proc usp_InsertDoctortbl
@empId char(5),
@docId char(4),
@licenseNo char(11),
@licenseDate date,
@rank varchar(25),
@Spec varchar(50)
as
begin
insert into Doctor
values (@empId, @docId, @licenseNo, @licenseDate,@rank, @Spec)
end
go
execute usp_InsertDoctortbl
@empId = 'Emp16',
@docId = 'MD07',
@licenseNo = 'GYB-66-7600',
@licenseDate = '2022-11-01',
@rank = 'Junior',
@Spec = 'Infectious Disease'
--EXERCISE # 10
--Create a stored Proc to deletes a record from RentalCust table with a given SSN
create procedure usp_RentalCust
@ssn varchar (11)
as
begin
delete
from RentalCust
where social = @ssn
end
go
execute usp_RentalCust '000-48-6789'
Select*
From RentalCust
--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
create proc usp_Hotelcust
@ssn varchar(11)
as
begin
delete
From HotelCust
where SSN =@ssn
end
Go
Select*
From HotelCust
--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
create proc usp_Customer
as
begin
select*
From HotelCust
where SUBSTRING(SSN,CHARINDEX('-',SSN)+1,2)= '45'
end
go
execute usp_Customer
--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
Alter proc usp_RentalCustDelete
@ssn varchar (11)
as
begin
delete
from RentalCust
where SUBSTRING(social, CHARINDEX('-', social)+1, 2) = '45'
end
go
Select*
From RentalCust
--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
execute RentalCustupdate
@ssn='903-00-4700',
@phone = '204-123-0988'
Select*
from RentalCust
--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:
: To modify
: To drop
DROP VIEW statement
AS
<Select statement>
GO
*/
--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.
Alter view vw_PatientDiagnosed
as
select*
from VW_Patient
go
--EXAMPLE - View # 03
--Check the result of vw_PatientDiagnosed by SELECT statement
Select*
from vw_PatientDiagnosed
--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
Select *
from vw_PatientDiagnosed
where [state] = 'MD'
--EXAMPLE - View # 05
--Modify vw_PatientDiagnosed so that it returns the patients diagnosed in year 2017
Select*
from vw_PatientDiagnosed
--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)
create view vw_EmployeesMD
as
select empId, concat(empFName, ' ', empLName) as FullName, DoB, [state]
from Employee
where [state] = 'MD'
go
--EXERCISE - View # 02
--Create view that displays mId, Medicine ID and the number of times each medicine
was
--prescribed.
create view vw_Medicine
as
select count(MP.mId) as numberofPriscription, M.mId
from Medicine M
join MedicinePrescribed MP on M.mId = MP.mId
group by M.mId
go
--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
Select*
From vw_Doctors
Select*
From vw_Medicines
-- 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
*/
- 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 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
--EXAMPLE : UDF # 02
--Create a udf that returns the average salary of a given employee type
--Note : UDF with parameter
--EXAMPLE : TVF # 01
--Create a user defined function, tvf_GetEmpTypeAndAVGSalary, that returns empType
and their
--corresponding Average Salaries. ( Creating UDF that returns a table )
--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 )
--Method (1)
--Method (2)
--of employees.
--Method (1)
--Method (2)
--Using Method(1)
--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.
--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.
*/
--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
with cte_Medicineprescribed
as
(Select mId, count(mId) as NumbOfMedicine
from MedicinePrescribed
group by mId)
--EXAMPLE - CTE # 02
--Create CTE that returns the average salaries of each type of employees
With CTE_AverageSalary
as
(Select empType, avg(Salary) as AverageSalary
From Employee
group by empType)
Select*
From CTE_AverageSalary
--EXERCISE - CTE # 01
--Modify the above code to sort the output by empType in descending order.
With CTE_AverageSalary
as
(Select empType, avg(Salary) as AverageSalary
From Employee
group by empType)
Select*
From CTE_AverageSalary
order by empType desc
--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.
with CTE_Patients
as
(Select prescriptionId, diagnosisNo, prescriptionDate
From Prescription)
Select*
From employee E
join CTE_AverageSalary CT on CT.empType = E.empType
Where Salary < AverageSalary
Select*
From Employee E
join CTE_AverageSalaryEachType CT on E.empType = CT.empType
Where Salary > AverageSalary
/********************************* 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,
AS
BEGIN
<your t-sql statement>
END
*/
Select*
From Disease
update Disease
set dType = 'Chronic'
where dId = '5'
Select*
From Disease
--Drop/Delete a trigger
Select*
From HotelCust
insert into HotelCust values ('Tamiru', 'Mammo', '013-19-3040', '1974-01-01')
Select*
From Medicine
update Medicine
Set qtyInStock = '400'
where mId = '1'
Select*
From rentalCust
Delete RentalCust
Where firstName = 'Janet'
/*
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.
*/
Select*
from MedicineInsertAudit
Select*
From Medicine
--Test how the trigger works by inserting one row data to Medicine 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.
Select*
from RentalCust
--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
alter table Doctor
drop constraint fk_Doctor_Employee_empId
--Step3: Create the trigger that inserts the deleted employee data into
Employee_Terminated_Archive table
--by checking the role of the employee
create trigger tr_DeletedEmployee
on Employee
after delete
as
begin
insert into Eployee_Terminated_Archive
select*
from deleted D
end
go
--Now test the trigger at work by deleting an Employee - employee data will be
archived, but
--the employee role wont be set as expected
Delete Employee
where empId = 'DMP01'
--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
-- 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
--Now create an instead of insert trigger on the view vw_DoctorEmployee -> that
takes the data and inserts into
--the tables individually
create trigger tr_DoctorEmployeeInsert
on vw_DctorEmployee
instead of insert
as
begin
insert into vw_DoctorEmployee
select empId, docId, empFName, empLName, DoB, SSN, licenseDate, licenseNo,
specialization, rank
from inserted I
end
go