Download as pdf or txt
Download as pdf or txt
You are on page 1of 27

1

Pharmaceutical Information and Tracking Database

CST 363: Introduction to Database Systems


Spring 2022

Team S.T.S- Strive to Succeed

David Kim, Gabe Williams, Cristian Vazquez


2

Introduction

The purpose of this project was to assist a drug store chain track pharmaceutical and
prescription related information. The information tracked ranged from simple details about a
patient or doctor to the cost and trade name of a particular drug. This database and data within
will help our client understand the trends that are occurring within the pharmaceutical field. This
may include questions such as which drugs cost more than the average for a particular
pharmacy or finding all prescribed drugs by a particular pharmaceutical company and the
quantity prescribed. With the assistance of this database, the client will be better equipped with
data to respond more efficiently to better serve their patients and assist pharmacies and
pharmaceutical companies reduce costs and maximize production.

Our client required that our team collect basic information from patients, doctors,
pharmacies, and pharmaceutical companies. For patients, the information included SSN, name,
age, address, and primary physician. The information required for doctors was similar to
patients with SSN and name but included specialty and experience. As for pharmacies, our
client required that we record the name, address, phone number, drug trade and price. The
information needed for pharmaceutical companies included the company name and number.
The drug data that our client required is trade name, generic name, and pharmacy. For
contracts, our client required that we record pharmacy, pharmaceutical company, contract start
date and end date, contract text, and supervisor assigned to the contract. Last, our client
required the following data be recorded for prescriptions: RX number, doctor name, patient
name.
3

Database Structure

Table Name Table Information

patient This table contains the patient data that includes patient id, SSN, name,
birthdate, address, and primary physician id.

doctor This table contains the data about a doctor limited to doctor id, SSN, name,
speciality, and the year in which the doctor started their practice.

drug This table contains the data related to a drug including drug id, trade name,
generic name, and pharmacy company that stocks the drug.

pharmacy This table contains the data related to a pharmacy including the pharmacy
id, pharmacy name, address, and phone number.

pharmacy_has This table contains the data related to drug inventory within a pharmacy and
_drugs at what price.

pc_company This table contains the data related to a pharmaceutical company including
name and phone number.

prescription This table contains the data related to prescriptions filled out by a physician
including RX number, doctor id, patient id, drug id, date prescribed, quantity
prescribed, pharmacy id that filled the prescription, and date filled.

contracts This table contains the data related to contracts between a pharmaceutical
company and pharmacy. This data includes contract id, pharmacy id,
pharmaceutical company name, contract start and end date, contract text,
and the supervisor for the contract.

Database Design
One of the requirements of the client was to input basic information about each entity.
This information included personal or company name, address, SSN, phone number, and much
more. The basic information requirement was addressed by creating attributes within each entity
that would capture those requirements for the client. Within those entities that capture the basic
information, our team created auto incremented IDs that would act as the primary key to identify
one entity from another.
Another requirement that was addressed was the need to capture that every patient has
a primary physician. Our team was able to address that with foreign key primary_physician_id
within the patient table which depends on a primary key column, doctor_id, within the doctor
table. This relationship between a doctor and patient is a one to many relationship and shown
within our ER diagram.
4

The next requirement on our list was the need to track a particular drug to a
pharmaceutical company while ensuring drugs are identified by their trade name. For this
requirement, our team created a drug and pharmaceutical company table. The drug table has
attributes to track the generic name and trade name. The drug table also features a drug id
tracking each unique drug entity and is set as the primary key in the table. In addition, we
created a foreign key, company, within the drug table to reference to the primary key within the
pharmaceutical company, pc_companyname. We mapped the relationship as a non identifying
one to one relationship and is shown within our ER diagram.
With that information, our team created the pharmacy and pharmacy_has_drugs table to
track every pharmacy location and their pricing for the drugs in stock. The pharmacy table holds
basic information about the pharmacy. That pharmacy table is linked to the
pharmacy_has_drugs table with a one to many relationship. The pharmacy_has_drugs table
holds information about the pricing and particular drug in stock. In addition, the table links the
drugs and pharmacy table using the pharmacy and drug ID. This is shown in our ER diagram to
represent that a pharmacy holds several kinds of drugs and there are several kinds of drugs at a
pharmacy.
Next, the prescription table was created to fulfill the requirement from the client to track
prescriptions given out to a patient from a doctor. Within the prescription table, the primary key
consists of the RX number. That column identifies the prescription that was made between a
doctor and a patient. There are multiple foreign keys within the table. Two foreign keys
reference the primary key columns doctor ID and patient ID showing a one to many relationship,
and one foreign key references a primary key column pharmacy ID that is a one to many
relationship. While those are important foreign keys for the prescription table, they are shown in
the ER diagram as non-identifying as the primary key within the table uniquely identifies the row.
In addition, the prescription table has date prescribed, date filled, and quantity within the table to
track dates and quantities.
Last, the client wanted to track long term contracts with pharmacies and pharmaceutical
companies. This requirement was fulfilled by creating the contracts table. The contracts table
contains a surrogate primary key that auto increments a contract id. The client did not specify
any unique identifiable attributes that could be used to identify one contract from another so our
team opted for the strategy mentioned earlier. Next, the table has two foreign keys linked to the
primary keys of the pharmaceutical company and pharmacy table. In our ER diagram, we show
a one to many relationship reflecting the fact that one pharmaceutical company and pharmacy
can have multiple contracts. To fulfill the rest of the requirements, the contract start and end
date, contract text, and supervisor attributes were added into the contracts table.
In the design phase, our team had to make some assumptions and constraints when
designing our database. One constraint that was added in our design was the max possible
price for a single drug. According to McQueen (2021), the max price for a prescription drug does
not exceed eighty-seven thousand dollars. With that data in hand, we added the constraint to
the column within the pharmacy table. Also, there was a constraint added to the
in_practice_since column in the doctors table. Practice start year of 1900 or 2022 is not possible
so this constraint would ensure the doctor had to have a starting year greater than or equal to
1900 and less than or equal to 2022. As for assumptions, the client never specified whether the
pharmaceutical companies and pharmacies tracked are all U.S. based or include international
5

clients. According to Twilio (n.d.), our team opted to record phone numbers using the E.164
format since that is better suited for outbound calling from any country.
6

ER Diagram
7

SQL Schema
-- MySQL Workbench Forward Engineering

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;


SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE,
SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERRO
R_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------

-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 ;
USE `mydb` ;

-- -----------------------------------------------------
-- Table `mydb`.`pc_company`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`pc_company` (
`pc_companyname` VARCHAR(50) NOT NULL,
`pc_companyphonenumber` VARCHAR(19) NOT NULL,
PRIMARY KEY (`pc_companyname`))
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`pharmacy`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`pharmacy` (
`pharmacy_id` INT NOT NULL AUTO_INCREMENT,
`p_name` VARCHAR(25) NOT NULL,
`p_address` VARCHAR(45) NOT NULL,
`p_phonenumber` VARCHAR(19) NOT NULL,
PRIMARY KEY (`pharmacy_id`))
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`doctor`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`doctor` (
`doctor_id` INT NOT NULL AUTO_INCREMENT,
`SSN` VARCHAR(11) NOT NULL,
`name` VARCHAR(50) NOT NULL,
`speciality` VARCHAR(30) NOT NULL,
`in_practice_since` CHAR(4) NOT NULL CHECK(in_practice_since >= 1900 AND in_practice_since <= 2022),
PRIMARY KEY (`doctor_id`))
ENGINE = InnoDB;
8

-- -----------------------------------------------------
-- Table `mydb`.`drug`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`drug` (
`drug_id` INT NOT NULL AUTO_INCREMENT,
`trade_name` VARCHAR(100) NOT NULL,
`generic_name` VARCHAR(100) NOT NULL,
`company` VARCHAR(50) NOT NULL,
PRIMARY KEY (`drug_id`),
INDEX `fk_drug_pc_company1_idx` (`company` ASC) VISIBLE,
CONSTRAINT `fk_drug_pc_company1`
FOREIGN KEY (`company`)
REFERENCES `mydb`.`pc_company` (`pc_companyname`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`patient`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`patient` (
`patient_id` INT NOT NULL AUTO_INCREMENT,
`SSN` VARCHAR(11) NOT NULL,
`name` VARCHAR(50) NOT NULL,
`birthdate` DATE NOT NULL,
`address` VARCHAR(100) NOT NULL,
`primary_physician_id` INT NOT NULL,
PRIMARY KEY (`patient_id`),
INDEX `fk_patient_doctor1_idx` (`primary_physician_id` ASC) VISIBLE,
CONSTRAINT `fk_patient_doctor1`
FOREIGN KEY (`primary_physician_id`)
REFERENCES `mydb`.`doctor` (`doctor_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`prescription`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`prescription` (
`rx_number` INT NOT NULL AUTO_INCREMENT,
`doctor_id` INT NOT NULL,
`patient_id` INT NOT NULL,
`drug_id` INT NOT NULL,
`date_prescribed` DATE NOT NULL,
`quantity_prescribed` DECIMAL(3,0) NOT NULL,
`pharmacy_id` INT NULL,
`date_filled` DATE NULL,
PRIMARY KEY (`rx_number`),
INDEX `fk_prescription_pharmacy_idx` (`pharmacy_id` ASC) VISIBLE,
INDEX `fk_prescription_doctor1_idx` (`doctor_id` ASC) VISIBLE,
9

INDEX `fk_prescription_drug1_idx` (`drug_id` ASC) VISIBLE,


INDEX `fk_prescription_patient1_idx` (`patient_id` ASC) VISIBLE,
CONSTRAINT `fk_prescription_pharmacy`
FOREIGN KEY (`pharmacy_id`)
REFERENCES `mydb`.`pharmacy` (`pharmacy_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_prescription_doctor1`
FOREIGN KEY (`doctor_id`)
REFERENCES `mydb`.`doctor` (`doctor_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_prescription_drug1`
FOREIGN KEY (`drug_id`)
REFERENCES `mydb`.`drug` (`drug_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_prescription_patient1`
FOREIGN KEY (`patient_id`)
REFERENCES `mydb`.`patient` (`patient_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`contracts`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`contracts` (
`c_id` INT NOT NULL AUTO_INCREMENT,
`pharmacy_id` INT NOT NULL,
`p_companyname` VARCHAR(45) NOT NULL,
`c_start_date` DATE NOT NULL,
`c_end_date` DATE NOT NULL,
`c_text` LONGTEXT NOT NULL,
`c_supervisor` VARCHAR(45) NOT NULL,
PRIMARY KEY (`c_id`),
INDEX `fk_contracts_pharmacy1_idx` (`pharmacy_id` ASC) VISIBLE,
INDEX `fk_contracts_pc_company1_idx` (`p_companyname` ASC) VISIBLE,
CONSTRAINT `fk_contracts_pharmacy1`
FOREIGN KEY (`pharmacy_id`)
REFERENCES `mydb`.`pharmacy` (`pharmacy_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_contracts_pc_company1`
FOREIGN KEY (`p_companyname`)
REFERENCES `mydb`.`pc_company` (`pc_companyname`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `mydb`.`pharmacy_has_drugs`
10

-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`pharmacy_has_drugs` (
`pharmacy_id` INT NOT NULL,
`drug_id` INT NOT NULL,
`drug_price` DECIMAL(7,2) NOT NULL CHECK(drug_price < 87000),
PRIMARY KEY (`pharmacy_id`, `drug_id`),
INDEX `fk_pharmacy_has_drugs_drug1_idx` (`drug_id` ASC) VISIBLE,
CONSTRAINT `fk_pharmacy_has_drugs_pharmacy1`
FOREIGN KEY (`pharmacy_id`)
REFERENCES `mydb`.`pharmacy` (`pharmacy_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_pharmacy_has_drugs_drug1`
FOREIGN KEY (`drug_id`)
REFERENCES `mydb`.`drug` (`drug_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
11

Questions of Interest

-- 1 Find all of the drug(s) that cost more than the average price of drugs in pharmacy
"Walgreens". Show the name and the price of the drug and order by price
select trade_name, drug_price from pharmacy_has_drugs
join (select avg(drug_price) as ave_price from pharmacy_has_drugs
NATURAL JOIN pharmacy group by p_name) as average_price
NATURAL JOIN drug
where pharmacy_has_drugs.pharmacy_id = (SELECT pharmacy_id FROM pharmacy WHERE
p_name LIKE "Wallgreens") and drug_price < ave_price
order by drug_price;

-- 2 Find all drugs created by Pfizer and show the number of prescriptions each drug has. Order
by drug name
select trade_name, count(*) from prescription
join drug on drug.drug_id = prescription.drug_id
JOIN pc_company ON drug.company = pc_company.pc_companyname
where pc_companyname = 'Pfizer'
group by trade_name
order by trade_name;

-- 3 Have two columns, column one labeled “patients” and column two labeled “doctors”.
-- Find the pairing of the patient with the highest amount of perscriptions and the doctor who
prescribed the most perscriptions
WITH patient_count_table
AS (SELECT patient.name, COUNT(prescription.patient_id) AS patient_count
FROM prescription JOIN patient ON patient.patient_id = prescription.patient_id GROUP BY
patient.name),
doctor_count_table
AS (SELECT doctor.name, COUNT(prescription.doctor_id) AS doctor_count
FROM prescription JOIN doctor ON prescription.doctor_id = doctor.doctor_id GROUP BY
doctor.name)
SELECT MAX(patient_count_table.name), MAX(doctor_count_table.name)
FROM patient_count_table, doctor_count_table;

-- 4 Find the company that has the least expensive drug to fill a patient's perscription RX #1.
select pharmacy.p_name, outer_drug.generic_name, MIN(pharmacy_has_drugs.drug_price)
FROM pharmacy
JOIN pharmacy_has_drugs ON pharmacy_has_drugs.pharmacy_id = pharmacy.pharmacy_id
join drug AS outer_drug on outer_drug.drug_id = pharmacy_has_drugs.drug_id
where outer_drug.generic_name = (SELECT drug.trade_name
FROM drug JOIN prescription
ON prescription.drug_id = drug.drug_id
WHERE prescription.rx_number = 1)
12

AND pharmacy_has_drugs.drug_price <= (SELECT MIN(pharmacy_has_drugs.drug_price)


FROM pharmacy_has_drugs JOIN drug ON pharmacy_has_drugs.drug_id = drug.drug_id
WHERE outer_drug.generic_name = (SELECT drug.trade_name
FROM drug JOIN prescription
ON prescription.drug_id = drug.drug_id
WHERE prescription.rx_number = 1))
group by outer_drug.generic_name, pharmacy.p_name;

-- 5 Find each company's total amount of money made from prescriptions (quantity*price)
SELECT pc_company.pc_companyname, SUM(prescription.quantity_prescribed *
pharmacy_has_drugs.drug_price) AS total_revenue
FROM prescription
JOIN pharmacy ON pharmacy.pharmacy_id = pharmacy.pharmacy_id
JOIN pharmacy_has_drugs ON pharmacy_has_drugs.pharmacy_id = pharmacy.pharmacy_id
JOIN drug ON drug.drug_id = pharmacy_has_drugs.drug_id
JOIN pc_company ON drug.company = pc_company.pc_companyname
GROUP BY pc_company.pc_companyname;
13

Conclusion
Our team was able to take the requirements from our client and translate them into a
database that can assist the client to better utilize and efficiently record data. We started by
creating the basic entities with the attributes specified by the client. These ranged from basic
information, such as name and phone number, to very specific data, such as drug trade name
and RX number for a prescription. Once the attributes were configured on the backend, our
team was able to map out the relationships between entities to enable linking between tables to
ensure that the specific requirements were met.
As this database continues to grow, our team does have one pressing issue that we
would like to address in the future. What occurs with the RX number once it reaches the digit
limit? According to CVS (n.d), the RX number consists of six digits. Is there a chance for
duplicate prescriptions, and should we switch to a surrogate key as a way to uniquely identify
prescriptions?
With this project completed, our team learned a lot from this experience. First, designing
a database requires more than one attempt to get right. After completing our first draft of the
design, we all noticed some mistakes and missing requirements from our database. Our team is
still unsure whether we had fully fulfilled the requirements of the clients due to the time
constraint placed by this project. Last, we all learned to not overlook attributes and review all of
them for constraints or issues that may occur. This through review will enable better data
consistency and less issues down the road as the database grows.
14

Sources
Formatting International Phone Numbers. (n.d.) Twilio. Retrieved January 24, 2022, from
https://support.twilio.com/hc/en-us/articles/223183008-Formatting-International-Phone-N
umbers

How to read a prescription bottle label. (n.d.) CVS. Retrieved January 24, 2022, from
https://www.cvs.com/content/pharmacy/rx-labels

McQueen, Hannah. (2021, September 7). The 20 Most Expensive Prescription Drugs in the
US. GoodRx. https://www.goodrx.com/healthcare-access/drug-cost-and-savin
gs/20-most-expensive-drugs-in-the-usa
15

Appendix A - Patient Registration - Screenshots

These screenshots show a successful registration of patient data with confirmation of success.

These screenshots highlight the input validation for the SSN field.
16

These screenshots highlight the input validation for the name and birthdate field.

These screenshots highlight the input validation for the city and state field.
17

These screenshots highlight the input validation for the zip code and primary physician field.

This screenshot highlights the validation for a primary physician that is appropriate for the age of
the patient.
18

Appendix B - Prescription Registration - Screenshots

These screenshots show the form filled with correct data. The next screenshot shows the
confirmation window of success.

These screenshots show the input validation for the doctor SSN and name.
19

These screenshots show the input validation for the patient SSN and name.

These screenshots show the input validation for the drug name and quantity.
20

Appendix C - Prescription To Be Filled Request - Screenshots

These screenshots show the form filled with correct data. The next screenshot shows the
confirmation window of success.
21

These screenshots highlight input validation for the rx number, patient name, and pharmacy
name.
22

Appendix D - Display/Update Patient Data - Screenshots

These screenshots highlight a successful patient lookup.

These screenshots highlight the original and modified entries for the patient. In this example, the
street, city, state, zip code, and primary physician name are changed.
23

These screenshots highlight the confirmation window stating that the update was successful. In
addition, the screenshot shows the updated values entered from the previous screenshots.

These screenshots highlight the input validation for the street and city field.
24

These screenshots highlight the input validation for the state and zip code field.

This screenshot highlights the input validation for the primary physician name.
25

Appendix E - Quantity Prescribed Report - Screenshots

The screenshot shows that the application is fully functional with the proper input showing the
prescribed amounts for a given drug name.

This screenshot highlights the input validation done at the drug name field and date fields.
26

Appendix F - Pharmacy Prescription Fill Drug Quantity Report -


Screenshots

This screenshot shows the output of the report with valid input showing the drug names and
quantity of each drug used.
27

This screenshot shows the input validation done for the pharmacy id and date fields.

You might also like