Databases | Tasks for Practical Class 8 (915-23 KII)
Creating Queries Using Standard Functions in PostgreSQL.
Variant 1: Library Management System
Scenario: You are managing a database for a local library. You need to perform various queries related to members, books, and loans.
Database Schema:
-- Drop tables if they exist (optional)
-- DROP TABLE IF EXISTS loans;
-- DROP TABLE IF EXISTS books;
-- DROP TABLE IF EXISTS members;
-- 1. Create the 'members' table
CREATE TABLE members (
member_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE, -- For LOWER() and UNIQUE practice
join_date DATE NOT NULL,
membership_level VARCHAR(10) DEFAULT 'Bronze', -- For CASE or NULLIF
postal_code VARCHAR(10) -- Might have extra spaces, for TRIM()
);
-- 2. Create the 'books' table
CREATE TABLE books (
book_id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
author VARCHAR(100),
isbn VARCHAR(20) UNIQUE, -- May have hyphens/spaces, for REPLACE()
publication_year INTEGER, -- For EXTRACT() or CAST()
list_price NUMERIC(7, 2) -- For ROUND(), CEIL(), FLOOR(), ABS()
);
-- 3. Create the 'loans' table
CREATE TABLE loans (
loan_id SERIAL PRIMARY KEY,
book_id INTEGER REFERENCES books(book_id),
member_id INTEGER REFERENCES members(member_id),
loan_date DATE NOT NULL DEFAULT CURRENT_DATE,
due_date DATE NOT NULL,
return_date DATE -- NULL if not returned, for COALESCE(), AGE()
);
-- Sample Data Insertion --
INSERT INTO members (first_name, last_name, email, join_date, membership_level, postal_code) VALUES
('Arthur', 'Dent', 'a.dent@galaxy.net', '2021-03-15', 'Silver', ' SW1A0AA'),
('Ford', 'Prefect', 'ford.p@betelgeuse.com', '2021-03-15', 'Gold', 'BG5-XQ1 '),
('Zaphod', 'Beeblebrox', 'z.beeblebrox@president.gov', '2022-11-01', NULL, 'HHGTTG'), -- NULL level
('Trillian', 'Astra', 'trillian@heartofgold.spc', '2020-08-25', 'Gold', ' E1 6AN'),
('Marvin', 'Android', 'paranoid.android@sirius.cyb', '2023-01-10', 'Bronze', ' ROBOT01');
INSERT INTO books (title, author, isbn, publication_year, list_price) VALUES
('The Hitchhiker''s Guide', 'Douglas Adams', '0-345-39180-2', 1979, 15.99),
('Dirk Gently''s Holistic Detective Agency', 'Douglas Adams', ' 0-671-69464-4', 1987, 18.50), -- Leading space ISBN
('Good Omens', 'Terry Pratchett & Neil Gaiman', '0-575-04800-X ', 1990, 22.00), -- Trailing space ISBN
('Stardust', 'Neil Gaiman', '0-380-97728-1', 1999, 14.75),
('Hyperion', 'Dan Simmons', '978-0553283686', 1989, 19.95);
INSERT INTO loans (book_id, member_id, loan_date, due_date, return_date) VALUES
(1, 1, '2023-10-01', '2023-10-15', '2023-10-14'),
(2, 2, '2023-10-05', '2023-10-26', NULL), -- Overdue
(3, 1, '2023-10-10', '2023-10-31', NULL), -- Not yet due (assume today is Oct 26th)
(4, 3, '2023-09-15', '2023-10-06', '2023-10-10'), -- Returned late
(5, 4, '2023-10-20', '2023-11-10', NULL),
(1, 5, '2023-08-01', '2023-08-22', NULL); -- Very overdue
Tasks for Variant 1:
- Member Full Names: Select the
member_id
and generate a full name string for each member by concatenating theirfirst_name
andlast_name
, separated by a space. Alias this column asfull_name
. - Cleaned ISBNs: Display the
title
andisbn
for all books. Clean theisbn
by removing both leading/trailing spaces and any hyphens (‘-‘). Alias the cleaned column ascleaned_isbn
. (Hint: You might needTRIM
andREPLACE
). - Membership Duration: Calculate how long each member has been part of the library as of
CURRENT_DATE
. Display the member’sfirst_name
,join_date
, and the calculated duration usingAGE()
. Alias the duration column asmembership_duration
. - Loan Status: For all loans, display the
loan_id
,due_date
, and a calculatedstatus
. The status should be ‘Overdue’ if thereturn_date
is NULL AND thedue_date
is beforeCURRENT_DATE
. The status should be ‘Returned’ ifreturn_date
is NOT NULL. Otherwise, the status should be ‘On Loan’. (Hint: UseCASE
and check forNULL
). - Book Pricing Categories: Show the
title
,list_price
, and aprice_category
for each book. Categorize as ‘Budget’ if price < $15.00, ‘Standard’ if price is between $15.00 and $19.99 (inclusive), and ‘Premium’ if $20.00 or more. - Member Email Lowercase: Display the
first_name
,last_name
, andemail
address for all members, ensuring the email address is entirely in lowercase. Alias the lowercase email column aslower_email
. - Book Title Abbreviation: Show the
book_id
and the first 15 characters of each book’stitle
. If the title is longer than 15 characters, append ‘…’. Alias this asshort_title
. (Hint: UseSUBSTRING
and potentiallyLENGTH
andCONCAT
/||
). - Loan Period: Calculate the number of days between the
loan_date
anddue_date
for each loan. Displayloan_id
and the calculated number of days asloan_period_days
. (Hint: Date subtraction results in an integer number of days). - Price Rounded Up: Display the
title
andlist_price
for each book, along with the price rounded UP to the nearest whole dollar amount. Alias this asprice_ceil
. - Membership Level Display: Show the
member_id
andfirst_name
. Also display themembership_level
. If themembership_level
is NULL, display ‘Standard’ instead. Alias this column aseffective_level
. (Hint: UseCOALESCE
). - Extract Join Quarter: Display the
first_name
andjoin_date
for each member. Also, extract the calendar quarter (1, 2, 3, or 4) from theirjoin_date
. Alias this asjoin_quarter
. (Hint: UseEXTRACT(QUARTER FROM ...)
). - Postal Code Cleanup: Display the
member_id
and thepostal_code
for each member, removing any leading or trailing spaces. Alias the cleaned column astrimmed_postal_code
. - Absolute Price Difference: Calculate the absolute difference between each book’s
list_price
and a target price of $18.00. Display thetitle
,list_price
, and the calculatedabsolute_difference
. - Numeric ISBN Check (Conceptual): Identify books where the
cleaned_isbn
(from Task 2 logic) contains non-numeric characters (excluding potential ‘X’ at the end, common in ISBN-10). This is more complex; for this assignment, simply check ifREPLACE(TRIM(isbn), '-', '')
results in NULL when attempting to cast to a NUMERIC type (useNULLIF
combined with a check or a more advanced technique if known, otherwise describe the logic). For a simpler version: Return NULL usingNULLIF
if thepublication_year
is exactly1990
. Alias this asnull_if_1990_pub
. - Member ID Padding: Display the
member_id
for all members, formatted as a 5-digit string with leading zeros (e.g., 1 becomes ‘00001’). Alias this asformatted_member_id
. (Hint: UseLPAD
after casting).
Variant 2: University Course Enrollment
Scenario: You are managing a database for university enrollments, tracking students, courses, and their grades.
Database Schema:
-- Drop tables if they exist (optional)
-- DROP TABLE IF EXISTS enrollments;
-- DROP TABLE IF EXISTS courses;
-- DROP TABLE IF EXISTS students;
-- 1. Create the 'students' table
CREATE TABLE students (
student_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
middle_name VARCHAR(50), -- Allows NULLs, for COALESCE
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL, -- For LOWER(), UNIQUE
date_of_birth DATE, -- For AGE(), EXTRACT()
major VARCHAR(50) -- For CASE, NULLIF
);
-- 2. Create the 'courses' table
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY,
course_code VARCHAR(15) UNIQUE NOT NULL, -- e.g., ' CS 101 ', for TRIM()
course_name VARCHAR(100) NOT NULL, -- For UPPER(), SUBSTRING()
credits NUMERIC(3, 1), -- e.g., 3.0, 1.5. For ROUND(), ABS()
department VARCHAR(50) -- For general queries
);
-- 3. Create the 'enrollments' table
CREATE TABLE enrollments (
enrollment_id SERIAL PRIMARY KEY,
student_id INTEGER REFERENCES students(student_id),
course_id INTEGER REFERENCES courses(course_id),
enrollment_date DATE DEFAULT CURRENT_DATE, -- For EXTRACT(), INTERVAL
grade NUMERIC(4, 1) -- e.g. 85.5, 92.0. Allows NULL if not graded. For CEIL(), FLOOR(), CASE
);
-- Sample Data Insertion --
INSERT INTO students (first_name, middle_name, last_name, email, date_of_birth, major) VALUES
('Alice', 'Marie', 'Wonder', 'alice.wonder@uni.edu', '2003-04-10', 'Literature'),
('Bob', NULL, 'Builder', 'bob.the.builder@uni.edu', '2002-08-20', 'Engineering'),
('Charlie', 'Chaplin', 'Jr', 'charlie.jr@uni.edu', '2004-01-05', NULL), -- NULL Major
('Dorothy', 'Gale', 'Oz', 'dorothy.oz@uni.edu', '2003-11-11', 'Meteorology'),
('Eve', 'Ada', 'Lovelace', 'eve.lovelace@uni.edu', '2002-12-15', 'Computer Science');
INSERT INTO courses (course_code, course_name, credits, department) VALUES
(' CS 101 ', 'Introduction to Programming', 3.0, 'Computer Science'), -- Spaces in code
('LIT 205', 'Modernist Poetry', 3.0, 'Literature'),
(' ENG 310', 'Structural Analysis', 4.0, 'Engineering'), -- Leading space
('MATH 150 ', 'Calculus I', 4.5, 'Mathematics'), -- Trailing space
('CS 336', 'Database Systems', 3.0, 'Computer Science');
INSERT INTO enrollments (student_id, course_id, enrollment_date, grade) VALUES
(1, 2, '2023-09-05', 88.5),
(2, 3, '2023-09-05', 92.0),
(1, 4, '2023-09-06', 75.0),
(3, 1, '2023-09-07', NULL), -- Not graded yet
(4, 4, '2023-09-06', 65.5),
(5, 1, '2023-09-07', 95.0),
(5, 5, '2023-09-08', NULL); -- Not graded yet
Tasks for Variant 2:
- Student Initials and Full Name: Display the
student_id
. Create afull_name
(First Last). Create aninitials
string using the first letter of thefirst_name
and the first letter of thelast_name
in uppercase (e.g., ‘AW’). If amiddle_name
exists, display it usingCOALESCE
(show ‘N/A’ if NULL), otherwise skip the middle name display for this task. - Cleaned Course Codes: Show the
course_name
and thecourse_code
after removing any leading or trailing whitespace. Alias the cleaned code asclean_code
. - Student Age Calculation: Calculate the current age of each student based on their
date_of_birth
as ofCURRENT_DATE
. Displayfirst_name
,last_name
,date_of_birth
, and the calculatedage
. - Enrollment Grade Status: Display the
enrollment_id
,student_id
,course_id
, and a calculatedgrade_status
. The status should be ‘Passed’ ifgrade
>= 60, ‘Failed’ ifgrade
< 60, and ‘Pending’ ifgrade
is NULL. - Course Credit Categories: Display the
course_name
,credits
, and acredit_category
. Categorize as ‘Low’ if credits < 3.0, ‘Standard’ if credits are 3.0 or 3.5, and ‘High’ if credits > 3.5. - Standardized Student Emails: Show the
student_id
,first_name
, andemail
, ensuring theemail
is entirely in lowercase. Alias this asstandard_email
. - Course Name Abbreviation: Display the
course_id
and the first 20 characters of thecourse_name
. Alias this asshort_course_name
. - Semester of Enrollment: Display the
enrollment_id
andenrollment_date
. Determine the semester of enrollment based on the month: Month 1-5 = ‘Spring’, Month 6-8 = ‘Summer’, Month 9-12 = ‘Fall’. Alias this asenrollment_semester
. (Hint: UseEXTRACT
andCASE
). - Grade Rounded Down: Display the
enrollment_id
andgrade
. Also show thegrade
rounded DOWN to the nearest whole number. Alias this asgrade_floor
. Handle cases where grade might be NULL (it should likely remain NULL). - Major Display: Display the
student_id
andfirst_name
. UseCOALESCE
to show the student’smajor
; if themajor
is NULL, display ‘Undeclared’. Alias this asdeclared_major
. - Years Since Birth Year: Extract the birth year for each student. Calculate the number of full years that have passed between their birth year and the current year. Display
first_name
,date_of_birth
, andyears_passed
. (Hint:EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM date_of_birth)
). - Absolute Grade Difference from Average: Calculate the absolute difference between each student’s
grade
in ‘Calculus I’ (Course ID 4) and the average grade for that course (assume average is 70.0 for this task). Displaystudent_id
,grade
, andabs_diff_from_avg
. Only include enrollments for Course ID 4 with non-null grades. - Find Null Majors: Use
NULLIF
to return NULL if a student’s major is ‘Literature’. Otherwise, return the major. Displaystudent_id
,first_name
,major
, and the result asnull_if_literature
. - Check Student ID Parity: Determine if a
student_id
is odd or even. Display thestudent_id
and ‘Even’ or ‘Odd’ asid_parity
. (Hint: UseMOD
or%
). - Course Code Padding: Display the
course_id
andclean_code
(from Task 2 logic). Create apadded_code
by padding theclean_code
on the right with spaces up to a total length of 10 characters. (Hint: UseRPAD
).
Variant 3: Project & Task Management
Scenario: You are managing a database for tracking projects, tasks assigned to employees, and their progress.
Database Schema:
-- Drop tables if they exist (optional)
-- DROP TABLE IF EXISTS tasks;
-- DROP TABLE IF EXISTS projects;
-- DROP TABLE IF EXISTS employees;
-- 1. Create the 'employees' table
CREATE TABLE employees (
emp_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
emp_code VARCHAR(10) UNIQUE, -- e.g., 'EMP001', for SUBSTRING, CAST
hire_date DATE NOT NULL, -- For AGE(), EXTRACT()
hourly_rate NUMERIC(6, 2), -- For ROUND(), numeric ops
department VARCHAR(50) -- For general queries, NULLIF
);
-- 2. Create the 'projects' table
CREATE TABLE projects (
project_id SERIAL PRIMARY KEY,
project_name VARCHAR(100) NOT NULL UNIQUE, -- For UPPER(), LENGTH()
client_name VARCHAR(100),
start_date DATE NOT NULL,
deadline_date DATE, -- Allows NULL, for COALESCE, CASE
budget NUMERIC(12, 2) -- For ABS(), CEIL()
);
-- 3. Create the 'tasks' table
CREATE TABLE tasks (
task_id SERIAL PRIMARY KEY,
project_id INTEGER REFERENCES projects(project_id),
assigned_to_emp_id INTEGER REFERENCES employees(emp_id), -- Allows NULL
task_name VARCHAR(255) NOT NULL,
estimated_hours NUMERIC(5, 1), -- e.g., 8.0, 2.5. For ROUND()
creation_date TIMESTAMP DEFAULT NOW(), -- For date/time functions
completion_date DATE -- NULL if not completed. For CASE, AGE()
);
-- Sample Data Insertion --
INSERT INTO employees (first_name, last_name, emp_code, hire_date, hourly_rate, department) VALUES
('Peter', 'Gibbons', 'EMP001', '2019-02-15', 35.00, 'Software'),
('Michael', 'Bolton', 'EMP002', '2018-07-01', 40.50, NULL), -- NULL Dept
('Samir', 'Nagheenanajar', 'EMP003', '2019-02-15', 38.75, 'Software'),
('Joanna', 'Planter', 'EMP004', '2020-11-20', 45.00, 'Management'),
('Bill', 'Lumbergh', 'EMP005', '2015-03-10', 75.00, 'Management');
INSERT INTO projects (project_name, client_name, start_date, deadline_date, budget) VALUES
('TPS Reports Automation', 'Initech', '2023-01-10', '2023-06-30', 50000.00),
('Website Redesign', 'Globex Corp', '2023-03-01', '2023-09-15', 75000.50),
('New Feature X', 'Initech', '2023-05-15', NULL, 30000.00), -- NULL Deadline
('Server Migration', 'Stark Industries', '2023-08-01', '2023-12-20', 120000.00);
INSERT INTO tasks (project_id, assigned_to_emp_id, task_name, estimated_hours, creation_date, completion_date) VALUES
(1, 1, 'Analyze current TPS report process', 8.0, '2023-01-12 10:00:00', '2023-01-20'),
(1, 3, 'Develop script for data extraction', 24.5, '2023-02-01 11:30:00', '2023-03-15'),
(2, 4, 'Create wireframes for new website', 16.0, '2023-03-05 09:00:00', NULL), -- Not completed
(2, NULL, 'Content population', 40.0, '2023-06-01 14:00:00', NULL), -- Unassigned
(3, 1, 'Define requirements for Feature X', 4.0, '2023-05-16 15:00:00', '2023-05-25'),
(4, 5, 'Plan migration strategy', 12.0, '2023-08-02 16:20:00', NULL),
(1, 5, 'Oversee TPS report testing', 6.5, '2023-04-01 08:00:00', '2023-06-10');
Tasks for Variant 3:
- Employee Full Name and Code: Display the
emp_id
. Concatenatefirst_name
andlast_name
intofull_name
. Also display theemp_code
. - Project Name Uppercase: Show the
project_id
and theproject_name
entirely in uppercase, aliased asupper_project_name
. - Employee Tenure: Calculate the duration each employee has been working at the company as of
CURRENT_DATE
. Displayemp_code
,hire_date
, and the calculatedtenure
usingAGE()
. - Task Status Determination: Display the
task_id
,task_name
,deadline_date
(from the associated project - requires a JOIN, assume you can look up the project deadline manually for now or just use taskcompletion_date
). Provide astatus
: ‘Completed’ ifcompletion_date
is NOT NULL, ‘Overdue’ ifcompletion_date
IS NULL AND the project’sdeadline_date
is beforeCURRENT_DATE
(if deadline exists), ‘In Progress’ otherwise. (Simplified for assignment: Use onlycompletion_date
. ‘Completed’ if NOT NULL, ‘Pending’ if NULL). - Project Budget Categories: Display
project_name
,budget
. Categorize projects based onbudget
: ‘Small’ if budget < 40000, ‘Medium’ if budget is between 40000 and 80000 (inclusive), ‘Large’ if budget > 80000. Alias asbudget_category
. - Estimated Hours Rounded: Show the
task_id
,task_name
, andestimated_hours
. Also display theestimated_hours
rounded to the nearest whole number. Alias this asrounded_hours
. - Employee Code Numeric Part: Extract the numeric part of the
emp_code
(assuming format ‘EMP’ followed by numbers). Displayemp_id
,emp_code
, and the extracted number asemp_number
. (Hint: UseSUBSTRING
and possiblyCAST
). - Days Until Project Deadline: For projects that have a
deadline_date
, calculate the number of days remaining fromCURRENT_DATE
until the deadline. Displayproject_name
,deadline_date
, anddays_remaining
. Handle cases where the deadline might be in the past (result will be negative). - Budget Rounded Up: Display the
project_name
andbudget
. Also show thebudget
rounded UP to the nearest 1000 dollars. Alias this asbudget_ceil_k
. (Hint: UseCEIL
carefully, maybe divide, ceil, then multiply, or useROUND
with negative precision appropriately if the goal is nearest 1000, useCEIL
if strictly UP). Let’s stick toCEIL
for the tutorial concept: displayCEIL(budget)
asbudget_ceil_dollar
. - Assigned Employee Display: Display
task_id
andtask_name
. UseCOALESCE
to show theassigned_to_emp_id
. If it’s NULL, display 0 instead. Alias this asassigned_emp
. - Project Start Month and Year: Extract the month and year from the
start_date
for each project. Displayproject_name
,start_date
,start_month
, andstart_year
. - Absolute Budget Deviation: Calculate the absolute difference between each project’s
budget
and a standard budget of $60,000. Displayproject_name
,budget
, andabs_budget_deviation
. - Task Creation Hour: Extract the hour (0-23) from the
creation_date
timestamp for each task. Displaytask_id
,creation_date
, andcreation_hour
. - Find Non-Software Employees: Use
NULLIF
to return NULL if an employee’s department is ‘Software’. Otherwise, return the department. Displayemp_id
,first_name
,department
, and the result asnull_if_software
. -
Format Hourly Rate: Display the emp_id, first_name, and hourly_rate. Create a new string column named formatted_rate that shows the hourly_rate prefixed with a dollar sign (‘$’). (Hint: Use the concatenation operator and cast the hourly_rate to VARCHAR).
Variant 4: E-commerce Order System
Scenario: You are managing the database for an online retail store. You need to query customer information, product details, orders, and the items within those orders.
Database Schema:
-- Drop tables if they exist (optional)
-- DROP TABLE IF EXISTS order_items;
-- DROP TABLE IF EXISTS orders;
-- DROP TABLE IF EXISTS products;
-- DROP TABLE IF EXISTS customers;
-- 1. Create the 'customers' table
CREATE TABLE customers (
customer_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL, -- For LOWER(), UNIQUE
registration_date DATE NOT NULL DEFAULT CURRENT_DATE, -- For AGE(), EXTRACT()
address_line1 VARCHAR(255),
city VARCHAR(100),
postal_code VARCHAR(20) -- Might have spaces, for TRIM()
);
-- 2. Create the 'products' table (different structure from tutorial)
CREATE TABLE products (
product_sku VARCHAR(50) PRIMARY KEY, -- e.g., 'ELEC-LAP-1001', 'BOOK-FIC-205A'
product_name VARCHAR(150) NOT NULL, -- For SUBSTRING(), UPPER()
description TEXT, -- For LENGTH() (on excerpt)
unit_price NUMERIC(10, 2) NOT NULL CHECK (unit_price > 0), -- For ROUND(), CEIL(), FLOOR(), ABS()
category VARCHAR(50), -- For CASE, NULLIF
stock_added_date DATE -- For INTERVAL calculation
);
-- 3. Create the 'orders' table
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES customers(customer_id),
order_date TIMESTAMP NOT NULL DEFAULT NOW(), -- For EXTRACT(), AGE()
shipping_address VARCHAR(500), -- Could be different from customer address, maybe NULL
order_status VARCHAR(20) DEFAULT 'Pending', -- e.g., 'Pending', 'Shipped', 'Delivered', 'Cancelled'
-- total_amount NUMERIC(12, 2) -- Usually calculated, but could be stored
discount_code VARCHAR(15) NULL -- For COALESCE
);
-- 4. Create the 'order_items' table (linking orders and products)
CREATE TABLE order_items (
item_id SERIAL PRIMARY KEY,
order_id INTEGER NOT NULL REFERENCES orders(order_id),
product_sku VARCHAR(50) NOT NULL REFERENCES products(product_sku),
quantity INTEGER NOT NULL CHECK (quantity > 0),
price_per_unit NUMERIC(10, 2) NOT NULL -- Price at the time of order
);
-- Sample Data Insertion --
INSERT INTO customers (first_name, last_name, email, registration_date, postal_code) VALUES
('Jane', 'Doe', 'jane.d@email.com', '2022-01-15', ' 12345 '),
('John', 'Smith', 'J.Smith@email.com', '2021-11-30', '98765'),
('Peter', 'Jones', 'peterjones@email.com', '2023-05-20', ' SW1A 0AA'),
('Mary', 'Brown', 'mary.b@email.com', '2022-01-15', NULL); -- NULL postal code
INSERT INTO products (product_sku, product_name, description, unit_price, category, stock_added_date) VALUES
('ELEC-LAP-1001', 'UltraBook X1', 'A thin and light laptop.', 1299.99, 'Electronics', '2023-01-10'),
('BOOK-FIC-205A', 'The Forgotten Realm', 'A fantasy novel.', 19.95, 'Books', '2023-02-15'),
('HOME-KIT-050', 'Smart Coffee Maker', 'Brews coffee remotely.', 89.50, 'Home Goods', '2023-03-01'),
('ELEC-CAM-300', 'Action Camera Pro', NULL, 249.00, 'Electronics', '2023-01-10'), -- NULL description
('BOOK-NF-110B', 'History of Computing', 'Covers major milestones.', 35.00, 'Books', '2022-12-01');
INSERT INTO orders (customer_id, order_date, order_status, discount_code) VALUES
(1, '2023-10-01 10:30:00', 'Shipped', 'FALL10'),
(2, '2023-10-15 14:00:00', 'Pending', NULL),
(1, '2023-10-20 09:00:00', 'Pending', NULL),
(3, '2023-08-10 11:00:00', 'Delivered', NULL),
(4, '2023-10-25 16:00:00', 'Pending', 'NEWCUST5');
INSERT INTO order_items (order_id, product_sku, quantity, price_per_unit) VALUES
(1, 'ELEC-LAP-1001', 1, 1299.99),
(1, 'HOME-KIT-050', 1, 85.00), -- Price slightly different at time of order
(2, 'BOOK-FIC-205A', 2, 19.95),
(3, 'HOME-KIT-050', 1, 89.50),
(4, 'BOOK-NF-110B', 1, 35.00),
(5, 'ELEC-CAM-300', 1, 249.00);
Tasks for Variant 4:
- Customer Full Name: Select
customer_id
and display the customer’s full name by concatenatingfirst_name
andlast_name
with a space in between. Alias the result asfull_name
. - Standardized Email Addresses: Display the
customer_id
andemail
address for all customers, ensuring theemail
is entirely in lowercase. Alias this asstandard_email
. - Customer Membership Duration: Calculate how long each customer has been registered (since
registration_date
) as ofCURRENT_DATE
. Displaycustomer_id
,registration_date
, and the duration usingAGE()
, aliased asmembership_duration
. - Cleaned Postal Codes: Display the
customer_id
andpostal_code
. If thepostal_code
is not NULL, show it after removing any leading or trailing spaces; otherwise, show ‘N/A’. Alias this ascleaned_postal_code
. (Hint: UseTRIM
andCOALESCE
). - Product SKU Analysis: For each product, extract the category part (before the first ‘-‘) and the core code part (between the first and second ‘-‘). Display
product_sku
, the extractedsku_category
, andsku_core
. (Hint: UseSUBSTRING
and potentiallyPOSITION
or fixed lengths if the pattern is consistent). Simplified for tutorial scope: Assume first part is 4 chars, second is 3 chars. ExtractSUBSTRING(product_sku FROM 1 FOR 4)
assku_category_prefix
andSUBSTRING(product_sku FROM 6 FOR 3)
assku_type_prefix
. - Product Pricing Tiers: Display
product_name
,unit_price
, and a calculatedprice_tier
. The tier should be ‘Budget’ if price < $50, ‘Mid-Range’ if price is $50 to $250 (inclusive), and ‘Premium’ if price > $250. Use aCASE
statement. - Order Item Total Value: For each item in
order_items
, calculate the total value (quantity * price_per_unit
). Displayitem_id
,order_id
,product_sku
, and the calculateditem_total
. - Days Since Order: For each order, calculate the number of full days that have passed since the
order_date
(ignore time part for simplicity). Displayorder_id
,order_date
, anddays_passed
. (Hint:CURRENT_DATE - CAST(order_date AS DATE)
). - Unit Price Rounded: Display
product_name
andunit_price
, along with theunit_price
rounded to the nearest whole dollar. Alias this asrounded_price
. - Minimum Shipping Charge: Display
product_name
andunit_price
. Calculate a hypothetical minimum shipping charge by rounding theunit_price
UP to the nearest dollar (CEIL
). Alias this asmin_ship_charge_base
. - Order Status Display: Display
order_id
andorder_status
. Create a columnis_processing
that showsTRUE
if theorder_status
is ‘Pending’, andFALSE
otherwise. (Hint: UseCASE
or a boolean expression). - Order Placement Hour: Extract the hour (0-23) from the
order_date
for each order. Displayorder_id
,order_date
, andorder_hour
. - Absolute Price Difference from $100: For each product, calculate the absolute difference between its
unit_price
and $100. Displayproduct_name
,unit_price
, andabs_diff_from_100
. - Formatted Product Price String: Display the
product_name
andunit_price
. Create a string representation of the price prefixed with ‘$’. Alias this asformatted_price
. (e.g., ‘$1299.99’). Use'$' || unit_price::VARCHAR
. - Padded Order ID: Display the
order_id
formatted as a 10-digit string with leading zeros (e.g., 1 becomes ‘0000000001’). Alias this asformatted_order_id
. UseLPAD
.
Variant 5: Event Management System
Scenario: You are managing a database for an event organizing company, tracking events, venues, attendee registrations, and payments.
Database Schema:
-- Drop tables if they exist (optional)
-- DROP TABLE IF EXISTS registrations;
-- DROP TABLE IF EXISTS attendees;
-- DROP TABLE IF EXISTS events;
-- DROP TABLE IF EXISTS venues;
-- 1. Create the 'venues' table
CREATE TABLE venues (
venue_id SERIAL PRIMARY KEY,
venue_name VARCHAR(100) NOT NULL UNIQUE, -- For UPPER(), LENGTH()
address VARCHAR(255),
city VARCHAR(100),
capacity INTEGER CHECK (capacity > 0), -- For MOD(), numeric ops
booking_cost NUMERIC(8, 2), -- For ROUND(), CEIL(), ABS()
contact_phone VARCHAR(20) -- e.g., ' 123-456-7890 ', for TRIM(), REPLACE()
);
-- 2. Create the 'events' table
CREATE TABLE events (
event_id SERIAL PRIMARY KEY,
event_name VARCHAR(150) NOT NULL, -- For SUBSTRING()
venue_id INTEGER REFERENCES venues(venue_id),
event_type VARCHAR(50), -- e.g., 'Conference', 'Workshop', 'Webinar', 'Gala'
start_datetime TIMESTAMP NOT NULL, -- For EXTRACT(), AGE(), INTERVAL
end_datetime TIMESTAMP, -- Can be NULL (e.g., single day event), check start/end duration
base_ticket_price NUMERIC(7, 2) DEFAULT 0.00 -- For CASE, NULLIF
);
-- 3. Create the 'attendees' table
CREATE TABLE attendees (
attendee_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL, -- For LOWER()
signup_date DATE DEFAULT CURRENT_DATE, -- For AGE()
company_name VARCHAR(100) -- Allows NULL, for COALESCE
);
-- 4. Create the 'registrations' table
CREATE TABLE registrations (
registration_id SERIAL PRIMARY KEY,
event_id INTEGER NOT NULL REFERENCES events(event_id),
attendee_id INTEGER NOT NULL REFERENCES attendees(attendee_id),
registration_time TIMESTAMP DEFAULT NOW(), -- For EXTRACT(), AGE()
ticket_type VARCHAR(20) DEFAULT 'Standard', -- e.g., 'Standard', 'VIP', 'EarlyBird'
final_price NUMERIC(7, 2), -- Price paid, could differ from base price
payment_status VARCHAR(15) -- e.g., 'Paid', 'Pending', 'Refunded', NULL
);
-- Sample Data Insertion --
INSERT INTO venues (venue_name, capacity, booking_cost, contact_phone) VALUES
('Grand Hall', 500, 5000.00, ' 111-222-3333 '),
('Convention Center East Wing', 1500, 12000.50, '444-555-6666'),
('Cozy Corner Room', 50, 800.75, NULL), -- NULL phone
('Online Platform', 10000, 200.00, ' N/A ');
INSERT INTO events (event_name, venue_id, event_type, start_datetime, end_datetime, base_ticket_price) VALUES
('Annual Tech Conference 2024', 2, 'Conference', '2024-09-10 09:00:00', '2024-09-12 17:00:00', 499.00),
('Data Science Workshop', 1, 'Workshop', '2024-07-15 10:00:00', '2024-07-15 16:30:00', 150.00),
('Introduction to SQL Webinar', 4, 'Webinar', '2024-05-20 14:00:00', NULL, 0.00), -- Free event, NULL end time
('Charity Gala Dinner', 1, 'Gala', '2024-11-01 19:00:00', '2024-11-01 23:00:00', 250.50);
INSERT INTO attendees (first_name, last_name, email, company_name) VALUES
('Alice', 'Wonder', 'alice.w@example.com', 'Curious Inc.'),
('Bob', 'Marley', 'bob.m@example.com', NULL), -- NULL company
('Charlie', 'Day', 'charlie.d@example.com', 'Paddy''s Pub'),
('Diana', 'Prince', 'diana.p@example.com', 'Themyscira Exports');
INSERT INTO registrations (event_id, attendee_id, registration_time, ticket_type, final_price, payment_status) VALUES
(1, 1, '2024-03-15 10:00:00', 'EarlyBird', 399.00, 'Paid'),
(1, 2, '2024-04-01 11:30:00', 'Standard', 499.00, 'Paid'),
(2, 3, '2024-06-10 16:00:00', 'Standard', 150.00, 'Pending'),
(3, 1, '2024-05-01 09:00:00', 'Standard', 0.00, 'Paid'), -- Free event
(4, 4, '2024-09-01 14:20:00', 'VIP', 350.00, 'Paid'),
(2, 4, '2024-07-01 13:00:00', 'Standard', 150.00, NULL); -- NULL payment status
Tasks for Variant 5:
- Attendee Full Name: Select
attendee_id
and display the attendee’s full name by concatenatingfirst_name
andlast_name
with a space. Alias the result asfull_name
. - Cleaned Venue Phone: Display the
venue_name
andcontact_phone
. Show thecontact_phone
after removing all spaces and hyphens. If the phone is NULL or ‘ N/A ‘, display ‘Not Available’. Alias this ascleaned_phone
. (Hint: UseREPLACE
,TRIM
,COALESCE
). - Event Duration: Calculate the duration of each event (
end_datetime
-start_datetime
). Ifend_datetime
is NULL, display NULL. Displayevent_name
,start_datetime
,end_datetime
, and the calculatedduration
(as an INTERVAL). - Time Since Registration: For each registration, calculate how long ago it occurred (
registration_time
) relative toNOW()
. Displayregistration_id
,registration_time
, and the duration usingAGE()
, aliased asregistration_age
. - Event Pricing Category: Display
event_name
andbase_ticket_price
. Create aprice_category
usingCASE
: ‘Free’ if price is 0, ‘Affordable’ if price > 0 and <= 100, ‘Standard’ if price > 100 and <= 300, ‘Premium’ if price > 300. - Standardized Attendee Emails: Display the
attendee_id
,first_name
, andemail
, ensuring theemail
is entirely in lowercase. Alias this asstandard_email
. - Venue Capacity Check: Display
venue_name
andcapacity
. Add a columnis_large_venue
which is TRUE if thecapacity
is greater than 1000, and FALSE otherwise. - Event Start Day: Extract the day of the week (e.g., ‘Monday’, ‘Tuesday’) from the
start_datetime
for each event. Displayevent_name
,start_datetime
, andstart_day
. (Hint: UseTO_CHAR
withEXTRACT(DOW FROM ...)
might be needed for the name, or just show the DOW number fromEXTRACT
). Let’s stick to the number:EXTRACT(DOW FROM start_datetime) AS start_dow
(0=Sun, 6=Sat in PG). - Venue Cost Rounded Up: Display
venue_name
andbooking_cost
. Calculate the cost rounded UP to the nearest $100. Alias this ascost_ceil_100
. (Hint:CEIL(booking_cost / 100.0) * 100
). - Attendee Company Display: Display
attendee_id
,first_name
. UseCOALESCE
to show thecompany_name
; if it’s NULL, display ‘Individual Attendee’. Alias this asaffiliation
. - Absolute Price Difference from Base: For registrations, calculate the absolute difference between the
final_price
and the event’sbase_ticket_price
(requires joiningregistrations
andevents
). Displayregistration_id
,base_ticket_price
,final_price
, andprice_difference
. - Identify Pending Payments: Use
NULLIF
to return theregistration_id
only if thepayment_status
is NOT ‘Paid’. Otherwise, return NULL. Displayregistration_id
,payment_status
, and the result asunpaid_registration_id
. - Short Event Name: Display the
event_id
and the first 30 characters of theevent_name
. Alias this asshort_event_name
. UseSUBSTRING
. - Padded Venue ID: Display the
venue_id
formatted as a 5-digit string with leading zeros. Alias this asformatted_venue_id
. UseLPAD
. - Days Until Event Start: For events starting in the future, calculate the number of days from
CURRENT_DATE
untilstart_datetime
. Displayevent_name
,start_datetime
, anddays_until_start
. Handle events in the past (result might be negative or filter them out). Usestart_datetime::DATE - CURRENT_DATE
.
Variant 6: Blog Platform
Scenario: You are managing the database for a multi-user blog platform, tracking users, posts, comments, and categories.
Database Schema:
-- Drop tables if they exist (optional)
-- DROP TABLE IF EXISTS comments;
-- DROP TABLE IF EXISTS posts;
-- DROP TABLE IF EXISTS categories;
-- DROP TABLE IF EXISTS users;
-- 1. Create the 'users' table
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(30) UNIQUE NOT NULL, -- For LENGTH(), LOWER()
email VARCHAR(100) UNIQUE NOT NULL, -- For LOWER()
full_name VARCHAR(100), -- For CONCAT (if split needed) or just display
join_date DATE NOT NULL DEFAULT CURRENT_DATE, -- For AGE(), EXTRACT()
profile_bio TEXT -- Allows NULL, for COALESCE, LENGTH()
-- password_hash VARCHAR(255) NOT NULL -- Not used in tasks
);
-- 2. Create the 'categories' table
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY,
category_name VARCHAR(50) UNIQUE NOT NULL, -- For UPPER(), REPLACE()
slug VARCHAR(60) UNIQUE -- e.g., 'data-science-basics', for LOWER(), REPLACE()
);
-- 3. Create the 'posts' table
CREATE TABLE posts (
post_id SERIAL PRIMARY KEY,
author_id INTEGER NOT NULL REFERENCES users(user_id),
category_id INTEGER REFERENCES categories(category_id),
title VARCHAR(200) NOT NULL, -- For SUBSTRING()
content TEXT, -- For LENGTH()
publish_datetime TIMESTAMP, -- Allows NULL for drafts. For EXTRACT(), AGE(), INTERVAL
last_updated TIMESTAMP DEFAULT NOW(),
status VARCHAR(15) DEFAULT 'Draft', -- 'Draft', 'Published', 'Archived' - For CASE, NULLIF
word_count INTEGER -- For MOD(), CEIL(), numeric ops
);
-- 4. Create the 'comments' table
CREATE TABLE comments (
comment_id SERIAL PRIMARY KEY,
post_id INTEGER NOT NULL REFERENCES posts(post_id),
commenter_id INTEGER REFERENCES users(user_id), -- NULL if commenter is anonymous/not logged in
commenter_name VARCHAR(50), -- Used if commenter_id is NULL
comment_text TEXT NOT NULL,
comment_datetime TIMESTAMP DEFAULT NOW(), -- For EXTRACT(), AGE()
parent_comment_id INTEGER REFERENCES comments(comment_id) -- For threaded comments (NULL if top-level)
);
-- Sample Data Insertion --
INSERT INTO users (username, email, full_name, join_date, profile_bio) VALUES
('john_doe', 'john.doe@blog.com', 'John Doe', '2022-01-10', 'Tech enthusiast and blogger.'),
('jane_smith', 'Jane.Smith@blog.com', 'Jane Smith', '2022-03-15', NULL), -- NULL bio
('bob_coder', 'bob@coder.net', 'Bob Coder', '2023-05-01', 'Software developer sharing tips.'),
('reader_x', 'readerX@mail.com', NULL, '2023-10-01', NULL); -- No full name, no bio
INSERT INTO categories (category_name, slug) VALUES
('Technology', 'technology'),
('Data Science', 'data-science'),
('Tutorials', 'tutorials'),
(' Opinion Pieces ', 'opinion-pieces'); -- Slug needs generating/cleaning
INSERT INTO posts (author_id, category_id, title, content, publish_datetime, status, word_count) VALUES
(1, 1, 'The Future of AI', 'AI is evolving rapidly...', '2023-06-01 10:00:00', 'Published', 1250),
(3, 2, 'Introduction to PostgreSQL Functions', 'This post covers several useful SQL functions...', '2023-07-15 14:30:00', 'Published', 1800),
(1, 3, 'Setting Up a Python Dev Environment', 'Step-by-step guide...', NULL, 'Draft', 950), -- Draft, no publish date
(2, 4, 'Why Static Sites Are Great', 'My thoughts on static site generators...', '2023-09-01 11:00:00', 'Published', 780),
(3, 1, 'Old Tech Thoughts', 'Some musings on older tech...', '2022-11-20 09:00:00', 'Archived', 600); -- Archived
INSERT INTO comments (post_id, commenter_id, commenter_name, comment_text, comment_datetime) VALUES
(1, 2, NULL, 'Great overview!', '2023-06-01 11:00:00'),
(2, 1, NULL, 'Very helpful, thanks Bob!', '2023-07-16 09:15:00'),
(1, NULL, 'Guest User', 'I disagree with point 2.', '2023-06-02 15:00:00'), -- Anonymous comment
(4, 3, NULL, 'Nice points, Jane!', '2023-09-01 12:30:00'),
(2, 4, NULL, 'Where can I learn more?', '2023-10-05 10:00:00');
Tasks for Variant 6:
- Username Length Check: Display the
user_id
andusername
. Also show the length of eachusername
, aliased asusername_length
. - Category Slug Generation: Display
category_name
. Generate a potentialslug
by convertingcategory_name
to lowercase, removing leading/trailing spaces, and replacing remaining spaces with hyphens. Alias this asgenerated_slug
. (UseLOWER
,TRIM
,REPLACE
). - User Account Age: Calculate how long each user has been registered (since
join_date
) as ofCURRENT_DATE
. Displayusername
,join_date
, and the duration usingAGE()
, aliased asaccount_age
. - Post Excerpt: For each post, display the
post_id
,title
, and the first 150 characters of thecontent
. If the content is longer than 150 characters, append ‘…’. Alias this aspost_excerpt
. (Hint: UseSUBSTRING
,LENGTH
,CASE
,CONCAT
/||
). - Standardized User Emails: Display the
user_id
,username
, andemail
, ensuring theemail
is entirely in lowercase. Alias this asstandard_email
. - Post Publication Age: For published posts (
publish_datetime
is NOT NULL), calculate how long ago they were published relative toNOW()
. Displaypost_id
,title
,publish_datetime
, and the duration usingAGE()
, aliased astime_since_publish
. - Comment Time Analysis: For each comment, extract the year, month, and hour from
comment_datetime
. Displaycomment_id
,comment_datetime
,comment_year
,comment_month
, andcomment_hour
. - Post Visibility Status: Display
post_id
,title
, andstatus
. Create a columnis_visible
usingCASE
: TRUE ifstatus
is ‘Published’, FALSE otherwise. - Post Word Count Parity: Display
post_id
,title
, andword_count
. Determine if theword_count
is ‘Even’ or ‘Odd’. Alias this asword_count_parity
. (Hint: UseMOD
or%
). - User Bio Display: Display
username
andprofile_bio
. UseCOALESCE
to show ‘No bio provided’ ifprofile_bio
is NULL or an empty string. (Hint:COALESCE(NULLIF(TRIM(profile_bio), ''), 'No bio provided')
). - Absolute Word Count Deviation: Calculate the absolute difference between each post’s
word_count
and a target length of 1000 words. Displaypost_id
,word_count
, andabs_diff_from_1000
. - Identify Non-Published Posts: Use
NULLIF
to return thepost_id
if the poststatus
is ‘Draft’ or ‘Archived’. Otherwise, return NULL. Displaypost_id
,status
, and the result asnon_published_post_id
. - Estimated Reading Time: Calculate an estimated reading time in minutes by dividing
word_count
by 200 (average words per minute) and rounding the result UP to the nearest whole number. Displaypost_id
,word_count
, andestimated_read_minutes
. (UseCEIL
). - Padded User ID: Display the
user_id
formatted as a 7-digit string with leading zeros. Alias this asformatted_user_id
. UseLPAD
. - Commenter Identification: Display
comment_id
andcomment_text
. Show the commenter’s identity: ifcommenter_id
is not NULL, display ‘User: ‘ followed by thecommenter_id
(cast to VARCHAR). Ifcommenter_id
is NULL, display ‘Guest: ‘ followed bycommenter_name
. Alias this ascommenter_identity
. (UseCASE
andCOALESCE
or nestedCASE
).
Submission Instructions
- Create a new Google Document. Example
- Submit Your Google Doc Link: Google Sheet
