solution_04_database_functions.py
SQL/solutions/solution_04_database_functions.py
"""
====================================================================
Solution 4: MySQL Database Functions with SQLAlchemy - Complete Solutions
====================================================================
This file contains complete, commented solutions for all exercises
in exercise_04_database_functions.sql. Each solution demonstrates:
1. Proper use of SQLAlchemy functions (not raw SQL)
2. Date and time manipulation functions
3. String manipulation and formatting functions
4. Mathematical and conditional functions
5. Aggregate functions and custom expressions
6. Performance optimization techniques
7. Error handling and validation
8. Real-world function usage scenarios
====================================================================
"""
# Import required libraries
from sqlalchemy import create_engine, Column, Integer, String, Text, DECIMAL, TIMESTAMP, Boolean, ForeignKey, Enum, JSON, Index, func, case, text, and_, or_, desc, asc
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.sql import func as sql_func
from datetime import datetime, date, timedelta
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Create base class for declarative models
Base = declarative_base()
class User(Base):
"""User model for function demonstrations"""
__tablename__ = 'users'
user_id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), unique=True, nullable=False)
email = Column(String(100), unique=True, nullable=False)
first_name = Column(String(50), nullable=False)
last_name = Column(String(50), nullable=False)
created_at = Column(TIMESTAMP, default=func.current_timestamp())
is_active = Column(Boolean, default=True)
# Relationships
orders = relationship("Order", back_populates="user")
class Order(Base):
"""Order model for function demonstrations"""
__tablename__ = 'orders'
order_id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('users.user_id'), nullable=False)
order_number = Column(String(20), unique=True, nullable=False)
total_amount = Column(DECIMAL(10, 2), nullable=False)
status = Column(Enum('pending', 'processing', 'shipped', 'delivered', 'cancelled'), default='pending')
order_date = Column(TIMESTAMP, default=func.current_timestamp())
# Relationships
user = relationship("User", back_populates="orders")
def get_session():
"""Create database session for demonstrations"""
host = os.getenv('DB_HOST', 'localhost')
port = int(os.getenv('DB_PORT', 3306))
user = os.getenv('DB_USER', 'student')
password = os.getenv('DB_PASSWORD', 'password123')
database = os.getenv('DB_NAME', 'learning_db')
connection_string = f"mysql+pymysql://{user}:{password}@{host}:{port}/{database}"
engine = create_engine(connection_string)
Session = sessionmaker(bind=engine)
return Session()
# ===================================================================
# EXERCISE 4.1: DATE AND TIME FUNCTIONS - SOLUTIONS
# ===================================================================
def exercise_4_1_date_time_functions():
"""
Complete solutions for date and time function exercises.
"""
print("=== Exercise 4.1: Date and Time Functions Solutions ===\n")
session = get_session()
try:
# 1. Get current date, time, and timestamp
print("1. Current Date, Time, and Timestamp:")
current_date = session.query(sql_func.current_date()).scalar()
current_time = session.query(sql_func.current_time()).scalar()
current_timestamp = session.query(sql_func.current_timestamp()).scalar()
print(f" Current Date: {current_date}")
print(f" Current Time: {current_time}")
print(f" Current Timestamp: {current_timestamp}")
# 2. Extract year, month, day from order dates
print("\n2. Extract Date Components:")
date_components = session.query(
Order.order_id,
Order.order_date,
sql_func.year(Order.order_date).label('order_year'),
sql_func.month(Order.order_date).label('order_month'),
sql_func.day(Order.order_date).label('order_day'),
sql_func.dayofweek(Order.order_date).label('day_of_week')
).limit(5).all()
for order in date_components:
print(f" Order {order.order_id}: {order.order_date}")
print(f" Year: {order.order_year}, Month: {order.order_month}, Day: {order.order_day}")
print(f" Day of Week: {order.day_of_week}")
# 3. Calculate the age of each order in days
print("\n3. Calculate Order Age in Days:")
order_ages = session.query(
Order.order_id,
Order.order_date,
sql_func.datediff(sql_func.current_date(), Order.order_date).label('age_days')
).limit(5).all()
for order in order_ages:
print(f" Order {order.order_id}: {order.age_days} days old")
# 4. Find orders from the last 30 days
print("\n4. Orders from Last 30 Days:")
recent_orders = session.query(
Order.order_id,
Order.order_date,
Order.total_amount
).filter(
Order.order_date >= sql_func.current_date() - text('INTERVAL 30 DAY')
).limit(5).all()
for order in recent_orders:
print(f" Order {order.order_id}: {order.order_date} - ${order.total_amount}")
# 5. Format order dates in different ways
print("\n5. Formatted Order Dates:")
formatted_dates = session.query(
Order.order_id,
Order.order_date,
sql_func.date_format(Order.order_date, '%Y-%m-%d').label('iso_date'),
sql_func.date_format(Order.order_date, '%M %d, %Y').label('readable_date'),
sql_func.date_format(Order.order_date, '%W').label('day_name')
).limit(5).all()
for order in formatted_dates:
print(f" Order {order.order_id}: {order.iso_date} | {order.readable_date} | {order.day_name}")
# 6. Add 30 days to order dates
print("\n6. Future Dates (30 days later):")
future_dates = session.query(
Order.order_id,
Order.order_date,
sql_func.date_add(Order.order_date, text('INTERVAL 30 DAY')).label('future_date')
).limit(5).all()
for order in future_dates:
print(f" Order {order.order_id}: {order.order_date} -> {order.future_date}")
# 7. Find orders by day of the week
print("\n7. Orders by Day of Week:")
orders_by_day = session.query(
sql_func.dayofweek(Order.order_date).label('day_of_week'),
sql_func.count(Order.order_id).label('order_count')
).group_by(sql_func.dayofweek(Order.order_date)).all()
for day in orders_by_day:
print(f" Day {day.day_of_week}: {day.order_count} orders")
# 8. Calculate business days between dates
print("\n8. Business Days Calculation:")
business_days = session.query(
Order.order_id,
Order.order_date,
sql_func.datediff(sql_func.current_date(), Order.order_date).label('total_days'),
# Approximate business days (excluding weekends)
sql_func.datediff(sql_func.current_date(), Order.order_date) -
sql_func.floor(sql_func.datediff(sql_func.current_date(), Order.order_date) / 7) * 2
).label('business_days').limit(5).all()
for order in business_days:
print(f" Order {order.order_id}: {order.total_days} total days")
print("\n✅ Date and Time Functions Solutions Completed")
except Exception as e:
print(f"❌ Error in date/time functions: {e}")
finally:
session.close()
# ===================================================================
# EXERCISE 4.2: STRING MANIPULATION FUNCTIONS - SOLUTIONS
# ===================================================================
def exercise_4_2_string_functions():
"""
Complete solutions for string manipulation function exercises.
"""
print("\n=== Exercise 4.2: String Manipulation Functions Solutions ===\n")
session = get_session()
try:
# 1. Concatenate first name and last name
print("1. Full Name Concatenation:")
full_names = session.query(
User.user_id,
User.first_name,
User.last_name,
sql_func.concat(User.first_name, ' ', User.last_name).label('full_name')
).limit(5).all()
for user in full_names:
print(f" User {user.user_id}: {user.full_name}")
# 2. Extract domain names from email addresses
print("\n2. Extract Email Domains:")
email_domains = session.query(
User.user_id,
User.email,
sql_func.substring(User.email, sql_func.locate('@', User.email) + 1).label('domain')
).limit(5).all()
for user in email_domains:
print(f" User {user.user_id}: {user.email} -> {user.domain}")
# 3. Convert usernames to uppercase and lowercase
print("\n3. Username Case Conversion:")
case_conversion = session.query(
User.user_id,
User.username,
sql_func.upper(User.username).label('upper_username'),
sql_func.lower(User.username).label('lower_username')
).limit(5).all()
for user in case_conversion:
print(f" User {user.user_id}: {user.username} -> {user.upper_username} / {user.lower_username}")
# 4. Find the length of email addresses
print("\n4. Email Address Lengths:")
email_lengths = session.query(
User.user_id,
User.email,
sql_func.length(User.email).label('email_length')
).limit(5).all()
for user in email_lengths:
print(f" User {user.user_id}: {user.email} (length: {user.email_length})")
# 5. Extract first 5 characters of usernames
print("\n5. First 5 Characters of Usernames:")
username_prefixes = session.query(
User.user_id,
User.username,
sql_func.left(User.username, 5).label('username_prefix')
).limit(5).all()
for user in username_prefixes:
print(f" User {user.user_id}: {user.username} -> {user.username_prefix}")
# 6. Replace underscores with spaces in usernames
print("\n6. Replace Underscores with Spaces:")
formatted_usernames = session.query(
User.user_id,
User.username,
sql_func.replace(User.username, '_', ' ').label('formatted_username')
).limit(5).all()
for user in formatted_usernames:
print(f" User {user.user_id}: {user.username} -> {user.formatted_username}")
# 7. Find the position of '@' symbol in email addresses
print("\n7. '@' Symbol Position in Emails:")
at_positions = session.query(
User.user_id,
User.email,
sql_func.locate('@', User.email).label('at_position')
).limit(5).all()
for user in at_positions:
print(f" User {user.user_id}: {user.email} -> '@' at position {user.at_position}")
# 8. Trim whitespace from user data
print("\n8. Trim Whitespace:")
# Create sample data with whitespace
sample_text = " Hello World "
trim_result = session.query(
sql_func.trim(sample_text).label('trimmed'),
sql_func.ltrim(sample_text).label('left_trimmed'),
sql_func.rtrim(sample_text).label('right_trimmed')
).first()
print(f" Original: '{sample_text}'")
print(f" Trimmed: '{trim_result.trimmed}'")
print(f" Left Trimmed: '{trim_result.left_trimmed}'")
print(f" Right Trimmed: '{trim_result.right_trimmed}'")
# 9. Create formatted usernames (First Last)
print("\n9. Formatted Usernames (Title Case):")
title_case_names = session.query(
User.user_id,
User.first_name,
User.last_name,
sql_func.concat(
sql_func.upper(sql_func.left(User.first_name, 1)),
sql_func.lower(sql_func.substring(User.first_name, 2)),
' ',
sql_func.upper(sql_func.left(User.last_name, 1)),
sql_func.lower(sql_func.substring(User.last_name, 2))
).label('title_case_name')
).limit(5).all()
for user in title_case_names:
print(f" User {user.user_id}: {user.title_case_name}")
# 10. Generate display names using COALESCE
print("\n10. Display Names with COALESCE:")
display_names = session.query(
User.user_id,
User.first_name,
User.last_name,
sql_func.coalesce(User.first_name, User.last_name, 'Unknown').label('display_name')
).limit(5).all()
for user in display_names:
print(f" User {user.user_id}: {user.display_name}")
print("\n✅ String Manipulation Functions Solutions Completed")
except Exception as e:
print(f"❌ Error in string functions: {e}")
finally:
session.close()
# ===================================================================
# EXERCISE 4.3: MATHEMATICAL FUNCTIONS - SOLUTIONS
# ===================================================================
def exercise_4_3_math_functions():
"""
Complete solutions for mathematical function exercises.
"""
print("\n=== Exercise 4.3: Mathematical Functions Solutions ===\n")
session = get_session()
try:
# 1. Round order amounts to 2 decimal places
print("1. Round Order Amounts:")
rounded_amounts = session.query(
Order.order_id,
Order.total_amount,
sql_func.round(Order.total_amount, 2).label('rounded_amount')
).limit(5).all()
for order in rounded_amounts:
print(f" Order {order.order_id}: {order.total_amount} -> {order.rounded_amount}")
# 2. Calculate ceiling and floor values
print("\n2. Ceiling and Floor Values:")
ceiling_floor = session.query(
Order.order_id,
Order.total_amount,
sql_func.ceil(Order.total_amount).label('ceiling'),
sql_func.floor(Order.total_amount).label('floor')
).limit(5).all()
for order in ceiling_floor:
print(f" Order {order.order_id}: {order.total_amount} -> Ceiling: {order.ceiling}, Floor: {order.floor}")
# 3. Calculate absolute values
print("\n3. Absolute Values:")
sample_values = [-15.5, 10.2, -3.7, 0, 25.8]
for value in sample_values:
abs_result = session.query(sql_func.abs(value).label('absolute')).first()
print(f" |{value}| = {abs_result.absolute}")
# 4. Calculate square root
print("\n4. Square Root Calculations:")
sqrt_values = session.query(
Order.order_id,
Order.total_amount,
sql_func.sqrt(Order.total_amount).label('square_root')
).limit(5).all()
for order in sqrt_values:
print(f" Order {order.order_id}: √{order.total_amount} = {order.square_root:.4f}")
# 5. Calculate power of 2
print("\n5. Power of 2 Calculations:")
power_values = session.query(
Order.order_id,
Order.total_amount,
sql_func.power(Order.total_amount, 2).label('squared')
).limit(5).all()
for order in power_values:
print(f" Order {order.order_id}: {order.total_amount}² = {order.squared}")
# 6. Calculate modulo 10
print("\n6. Modulo 10 Calculations:")
modulo_values = session.query(
Order.order_id,
Order.total_amount,
sql_func.mod(Order.total_amount, 10).label('mod_10')
).limit(5).all()
for order in modulo_values:
print(f" Order {order.order_id}: {order.total_amount} MOD 10 = {order.mod_10}")
# 7. Generate random numbers
print("\n7. Random Numbers:")
random_numbers = session.query(
sql_func.rand().label('random_1'),
sql_func.rand().label('random_2'),
sql_func.rand().label('random_3')
).first()
print(f" Random 1: {random_numbers.random_1:.6f}")
print(f" Random 2: {random_numbers.random_2:.6f}")
print(f" Random 3: {random_numbers.random_3:.6f}")
# 8. Calculate percentage of total
print("\n8. Percentage of Total:")
total_amount = session.query(sql_func.sum(Order.total_amount)).scalar()
percentages = session.query(
Order.order_id,
Order.total_amount,
sql_func.round((Order.total_amount / total_amount) * 100, 2).label('percentage')
).limit(5).all()
for order in percentages:
print(f" Order {order.order_id}: {order.total_amount} ({order.percentage}% of total)")
# 9. Calculate running totals
print("\n9. Running Totals:")
running_totals = session.query(
Order.order_id,
Order.total_amount,
sql_func.sum(Order.total_amount).over(order_by=Order.order_id).label('running_total')
).limit(5).all()
for order in running_totals:
print(f" Order {order.order_id}: {order.total_amount} (Running Total: {order.running_total})")
# 10. Calculate moving averages
print("\n10. Moving Averages:")
moving_averages = session.query(
Order.order_id,
Order.total_amount,
sql_func.avg(Order.total_amount).over(
order_by=Order.order_id,
rows=(0, 2) # Current row and 2 preceding rows
).label('moving_avg')
).limit(5).all()
for order in moving_averages:
print(f" Order {order.order_id}: {order.total_amount} (Moving Avg: {order.moving_avg:.2f})")
print("\n✅ Mathematical Functions Solutions Completed")
except Exception as e:
print(f"❌ Error in math functions: {e}")
finally:
session.close()
# ===================================================================
# EXERCISE 4.4: CONDITIONAL FUNCTIONS - SOLUTIONS
# ===================================================================
def exercise_4_4_conditional_functions():
"""
Complete solutions for conditional function exercises.
"""
print("\n=== Exercise 4.4: Conditional Functions Solutions ===\n")
session = get_session()
try:
# 1. Categorize orders as 'High' or 'Low' value
print("1. Order Value Categories:")
value_categories = session.query(
Order.order_id,
Order.total_amount,
sql_func.if_(Order.total_amount > 100, 'High Value', 'Low Value').label('category')
).limit(5).all()
for order in value_categories:
print(f" Order {order.order_id}: {order.total_amount} -> {order.category}")
# 2. Nested IF functions for tier categories
print("\n2. Tier Categories with Nested IF:")
tier_categories = session.query(
Order.order_id,
Order.total_amount,
sql_func.if_(
Order.total_amount > 200,
'Premium',
sql_func.if_(
Order.total_amount > 100,
'High',
sql_func.if_(
Order.total_amount > 50,
'Medium',
'Low'
)
)
).label('tier')
).limit(5).all()
for order in tier_categories:
print(f" Order {order.order_id}: {order.total_amount} -> {order.tier}")
# 3. Handle NULL values with IFNULL
print("\n3. Handle NULL Values with IFNULL:")
null_handling = session.query(
User.user_id,
User.first_name,
sql_func.ifnull(User.first_name, 'Unknown').label('safe_name')
).limit(5).all()
for user in null_handling:
print(f" User {user.user_id}: {user.safe_name}")
# 4. Use COALESCE for first non-NULL value
print("\n4. COALESCE for First Non-NULL Value:")
coalesce_values = session.query(
User.user_id,
User.first_name,
User.last_name,
User.username,
sql_func.coalesce(User.first_name, User.last_name, User.username, 'No Name').label('display_name')
).limit(5).all()
for user in coalesce_values:
print(f" User {user.user_id}: {user.display_name}")
# 5. CASE statements for status descriptions
print("\n5. CASE Statements for Status Descriptions:")
status_descriptions = session.query(
Order.order_id,
Order.status,
case(
(Order.status == 'pending', 'Waiting for Processing'),
(Order.status == 'processing', 'Being Processed'),
(Order.status == 'shipped', 'On the Way'),
(Order.status == 'delivered', 'Successfully Delivered'),
(Order.status == 'cancelled', 'Order Cancelled'),
else_='Unknown Status'
).label('status_description')
).limit(5).all()
for order in status_descriptions:
print(f" Order {order.order_id}: {order.status} -> {order.status_description}")
# 6. CASE with multiple conditions
print("\n6. CASE with Multiple Conditions:")
complex_categories = session.query(
Order.order_id,
Order.total_amount,
Order.status,
case(
(and_(Order.total_amount > 200, Order.status == 'delivered'), 'Premium Delivered'),
(and_(Order.total_amount > 100, Order.status == 'delivered'), 'High Value Delivered'),
(Order.total_amount > 200, 'Premium'),
(Order.total_amount > 100, 'High Value'),
(Order.status == 'delivered', 'Delivered'),
else_='Standard'
).label('complex_category')
).limit(5).all()
for order in complex_categories:
print(f" Order {order.order_id}: {order.total_amount}, {order.status} -> {order.complex_category}")
# 7. Conditional calculations
print("\n7. Conditional Calculations:")
conditional_calculations = session.query(
Order.order_id,
Order.total_amount,
Order.status,
case(
(Order.status == 'delivered', Order.total_amount * 1.1), # 10% bonus for delivered
(Order.status == 'shipped', Order.total_amount * 1.05), # 5% bonus for shipped
else_=Order.total_amount
).label('adjusted_amount')
).limit(5).all()
for order in conditional_calculations:
print(f" Order {order.order_id}: {order.total_amount} -> {order.adjusted_amount}")
# 8. NULLIF to convert empty strings to NULL
print("\n8. NULLIF for Empty Strings:")
nullif_examples = session.query(
User.user_id,
User.username,
sql_func.nullif(User.username, '').label('nullified_username')
).limit(5).all()
for user in nullif_examples:
print(f" User {user.user_id}: {repr(user.username)} -> {repr(user.nullified_username)}")
# 9. Conditional formatting
print("\n9. Conditional Formatting:")
conditional_formatting = session.query(
Order.order_id,
Order.total_amount,
case(
(Order.total_amount > 100, sql_func.concat('$', sql_func.format(Order.total_amount, 2), ' (High Value)')),
else_=sql_func.concat('$', sql_func.format(Order.total_amount, 2))
).label('formatted_amount')
).limit(5).all()
for order in conditional_formatting:
print(f" Order {order.order_id}: {order.formatted_amount}")
# 10. Priority assignment based on multiple criteria
print("\n10. Priority Assignment:")
priority_assignment = session.query(
Order.order_id,
Order.total_amount,
Order.status,
case(
(and_(Order.total_amount > 200, Order.status == 'pending'), 'High Priority'),
(and_(Order.total_amount > 100, Order.status == 'pending'), 'Medium Priority'),
(Order.status == 'pending', 'Low Priority'),
else_='No Priority'
).label('priority')
).limit(5).all()
for order in priority_assignment:
print(f" Order {order.order_id}: {order.total_amount}, {order.status} -> {order.priority}")
print("\n✅ Conditional Functions Solutions Completed")
except Exception as e:
print(f"❌ Error in conditional functions: {e}")
finally:
session.close()
# ===================================================================
# EXERCISE 4.5: AGGREGATE FUNCTIONS - SOLUTIONS
# ===================================================================
def exercise_4_5_aggregate_functions():
"""
Complete solutions for aggregate function exercises.
"""
print("\n=== Exercise 4.5: Aggregate Functions Solutions ===\n")
session = get_session()
try:
# 1. Calculate total count of orders
print("1. Total Order Count:")
total_count = session.query(sql_func.count(Order.order_id)).scalar()
print(f" Total Orders: {total_count}")
# 2. Calculate sum, average, min, max of order amounts
print("\n2. Order Amount Statistics:")
amount_stats = session.query(
sql_func.sum(Order.total_amount).label('total_amount'),
sql_func.avg(Order.total_amount).label('average_amount'),
sql_func.min(Order.total_amount).label('min_amount'),
sql_func.max(Order.total_amount).label('max_amount')
).first()
print(f" Total Amount: ${amount_stats.total_amount}")
print(f" Average Amount: ${amount_stats.average_amount:.2f}")
print(f" Min Amount: ${amount_stats.min_amount}")
print(f" Max Amount: ${amount_stats.max_amount}")
# 3. Count orders by status
print("\n3. Order Count by Status:")
status_counts = session.query(
Order.status,
sql_func.count(Order.order_id).label('order_count')
).group_by(Order.status).all()
for status in status_counts:
print(f" {status.status}: {status.order_count} orders")
# 4. Calculate total amount by status
print("\n4. Total Amount by Status:")
status_totals = session.query(
Order.status,
sql_func.sum(Order.total_amount).label('total_amount'),
sql_func.avg(Order.total_amount).label('average_amount')
).group_by(Order.status).all()
for status in status_totals:
print(f" {status.status}: ${status.total_amount} (avg: ${status.average_amount:.2f})")
# 5. Find average order amount by user
print("\n5. Average Order Amount by User:")
user_averages = session.query(
Order.user_id,
sql_func.count(Order.order_id).label('order_count'),
sql_func.avg(Order.total_amount).label('average_amount'),
sql_func.sum(Order.total_amount).label('total_amount')
).group_by(Order.user_id).limit(5).all()
for user in user_averages:
print(f" User {user.user_id}: {user.order_count} orders, avg: ${user.average_amount:.2f}, total: ${user.total_amount}")
# 6. Calculate percentage of orders by status
print("\n6. Percentage of Orders by Status:")
total_orders = session.query(sql_func.count(Order.order_id)).scalar()
status_percentages = session.query(
Order.status,
sql_func.count(Order.order_id).label('order_count'),
sql_func.round((sql_func.count(Order.order_id) / total_orders) * 100, 2).label('percentage')
).group_by(Order.status).all()
for status in status_percentages:
print(f" {status.status}: {status.order_count} orders ({status.percentage}%)")
# 7. Find top 5 users by total order amount
print("\n7. Top 5 Users by Total Order Amount:")
top_users = session.query(
Order.user_id,
sql_func.sum(Order.total_amount).label('total_amount'),
sql_func.count(Order.order_id).label('order_count')
).group_by(Order.user_id).order_by(desc(sql_func.sum(Order.total_amount))).limit(5).all()
for user in top_users:
print(f" User {user.user_id}: ${user.total_amount} ({user.order_count} orders)")
# 8. Calculate running totals by date
print("\n8. Running Totals by Date:")
running_totals = session.query(
Order.order_id,
Order.order_date,
Order.total_amount,
sql_func.sum(Order.total_amount).over(
order_by=Order.order_date
).label('running_total')
).limit(5).all()
for order in running_totals:
print(f" Order {order.order_id}: {order.order_date} - ${order.total_amount} (Running Total: ${order.running_total})")
# 9. Find orders above average amount
print("\n9. Orders Above Average Amount:")
average_amount = session.query(sql_func.avg(Order.total_amount)).scalar()
above_average = session.query(
Order.order_id,
Order.total_amount,
sql_func.round(Order.total_amount - average_amount, 2).label('above_average')
).filter(Order.total_amount > average_amount).limit(5).all()
for order in above_average:
print(f" Order {order.order_id}: ${order.total_amount} (${order.above_average} above average)")
# 10. Calculate cumulative percentages
print("\n10. Cumulative Percentages:")
cumulative_percentages = session.query(
Order.order_id,
Order.total_amount,
sql_func.round(
(sql_func.sum(Order.total_amount).over(order_by=Order.order_id) /
sql_func.sum(Order.total_amount).over()) * 100, 2
).label('cumulative_percentage')
).limit(5).all()
for order in cumulative_percentages:
print(f" Order {order.order_id}: ${order.total_amount} ({order.cumulative_percentage}% cumulative)")
print("\n✅ Aggregate Functions Solutions Completed")
except Exception as e:
print(f"❌ Error in aggregate functions: {e}")
finally:
session.close()
# ===================================================================
# EXERCISE 4.6: CUSTOM FUNCTION CREATION - SOLUTIONS
# ===================================================================
def exercise_4_6_custom_functions():
"""
Complete solutions for custom function creation exercises.
"""
print("\n=== Exercise 4.6: Custom Function Creation Solutions ===\n")
session = get_session()
try:
# 1. Create a custom function to format currency
print("1. Custom Currency Formatting:")
def format_currency(amount_column):
return sql_func.concat('$', sql_func.format(amount_column, 2))
currency_formatted = session.query(
Order.order_id,
Order.total_amount,
format_currency(Order.total_amount).label('formatted_amount')
).limit(5).all()
for order in currency_formatted:
print(f" Order {order.order_id}: {order.formatted_amount}")
# 2. Create a custom function to calculate order age in weeks
print("\n2. Custom Order Age in Weeks:")
def calculate_age_weeks(date_column):
return sql_func.round(sql_func.datediff(sql_func.current_date(), date_column) / 7, 1)
age_weeks = session.query(
Order.order_id,
Order.order_date,
calculate_age_weeks(Order.order_date).label('age_weeks')
).limit(5).all()
for order in age_weeks:
print(f" Order {order.order_id}: {order.age_weeks} weeks old")
# 3. Create a custom function to generate order summaries
print("\n3. Custom Order Summaries:")
def generate_order_summary():
return sql_func.concat(
'Order #', Order.order_number,
' - $', sql_func.format(Order.total_amount, 2),
' - ', sql_func.upper(Order.status)
)
order_summaries = session.query(
Order.order_id,
generate_order_summary().label('order_summary')
).limit(5).all()
for order in order_summaries:
print(f" {order.order_summary}")
# 4. Create a custom function to categorize orders by multiple criteria
print("\n4. Custom Order Categorization:")
def categorize_order():
return case(
(and_(Order.total_amount > 200, Order.status == 'delivered'), 'Premium Delivered'),
(and_(Order.total_amount > 100, Order.status == 'delivered'), 'High Value Delivered'),
(Order.total_amount > 200, 'Premium'),
(Order.total_amount > 100, 'High Value'),
(Order.status == 'delivered', 'Delivered'),
else_='Standard'
)
order_categories = session.query(
Order.order_id,
Order.total_amount,
Order.status,
categorize_order().label('category')
).limit(5).all()
for order in order_categories:
print(f" Order {order.order_id}: {order.total_amount}, {order.status} -> {order.category}")
# 5. Create a custom function to format user display names
print("\n5. Custom User Display Names:")
def format_display_name():
return sql_func.concat(
sql_func.upper(sql_func.left(User.first_name, 1)),
sql_func.lower(sql_func.substring(User.first_name, 2)),
' ',
sql_func.upper(sql_func.left(User.last_name, 1)),
sql_func.lower(sql_func.substring(User.last_name, 2))
)
display_names = session.query(
User.user_id,
format_display_name().label('display_name')
).limit(5).all()
for user in display_names:
print(f" User {user.user_id}: {user.display_name}")
# 6. Create a custom function to calculate order priority scores
print("\n6. Custom Order Priority Scores:")
def calculate_priority_score():
return case(
(and_(Order.total_amount > 200, Order.status == 'pending'), 100),
(and_(Order.total_amount > 100, Order.status == 'pending'), 75),
(Order.total_amount > 200, 50),
(Order.status == 'pending', 25),
else_=0
)
priority_scores = session.query(
Order.order_id,
Order.total_amount,
Order.status,
calculate_priority_score().label('priority_score')
).limit(5).all()
for order in priority_scores:
print(f" Order {order.order_id}: {order.total_amount}, {order.status} -> Score: {order.priority_score}")
# 7. Create a custom function to generate status descriptions
print("\n7. Custom Status Descriptions:")
def generate_status_description():
return case(
(Order.status == 'pending', 'Waiting for Processing'),
(Order.status == 'processing', 'Being Processed'),
(Order.status == 'shipped', 'On the Way'),
(Order.status == 'delivered', 'Successfully Delivered'),
(Order.status == 'cancelled', 'Order Cancelled'),
else_='Unknown Status'
)
status_descriptions = session.query(
Order.order_id,
Order.status,
generate_status_description().label('status_description')
).limit(5).all()
for order in status_descriptions:
print(f" Order {order.order_id}: {order.status} -> {order.status_description}")
# 8. Create a custom function to calculate business metrics
print("\n8. Custom Business Metrics:")
def calculate_business_metrics():
return sql_func.concat(
'Orders: ', sql_func.count(Order.order_id),
' | Total: $', sql_func.format(sql_func.sum(Order.total_amount), 2),
' | Avg: $', sql_func.format(sql_func.avg(Order.total_amount), 2)
)
business_metrics = session.query(calculate_business_metrics().label('metrics')).first()
print(f" Business Metrics: {business_metrics.metrics}")
# 9. Create a custom function to format dates in multiple ways
print("\n9. Custom Date Formatting:")
def format_date_multiple_ways():
return sql_func.concat(
sql_func.date_format(Order.order_date, '%Y-%m-%d'), ' | ',
sql_func.date_format(Order.order_date, '%M %d, %Y'), ' | ',
sql_func.date_format(Order.order_date, '%W')
)
formatted_dates = session.query(
Order.order_id,
format_date_multiple_ways().label('formatted_date')
).limit(5).all()
for order in formatted_dates:
print(f" Order {order.order_id}: {order.formatted_date}")
# 10. Create a custom function to generate report headers
print("\n10. Custom Report Headers:")
def generate_report_header():
return sql_func.concat(
'Order Report - Generated on ',
sql_func.date_format(sql_func.current_timestamp(), '%M %d, %Y at %H:%i:%s')
)
report_header = session.query(generate_report_header().label('header')).first()
print(f" {report_header.header}")
print("\n✅ Custom Function Creation Solutions Completed")
except Exception as e:
print(f"❌ Error in custom functions: {e}")
finally:
session.close()
# ===================================================================
# MAIN FUNCTION TO RUN ALL SOLUTIONS
# ===================================================================
def main():
"""
Main function to run all database function exercise solutions.
"""
print("=== MySQL Database Functions with SQLAlchemy - Complete Solutions ===\n")
try:
# Run all exercise solutions
exercise_4_1_date_time_functions()
exercise_4_2_string_functions()
exercise_4_3_math_functions()
exercise_4_4_conditional_functions()
exercise_4_5_aggregate_functions()
exercise_4_6_custom_functions()
print("\n=== All Database Function Solutions Completed Successfully ===")
except Exception as e:
print(f"❌ Error running solutions: {e}")
# Standard Python idiom for running the script
if __name__ == "__main__":
main()
Bài viết liên quan
COM641_Task3_Solutions.sql
COM641_Task3_Solutions.sql — sql source code from the SQL learning materials (SQL/assignment/COM641_Task3_Solutions.sql).
Đọc bài viết →exercise_01_basic_queries.sql
exercise_01_basic_queries.sql — sql source code from the SQL learning materials (SQL/exercises/exercise_01_basic_queries.sql).
Đọc bài viết →exercise_02_joins.sql
exercise_02_joins.sql — sql source code from the SQL learning materials (SQL/exercises/exercise_02_joins.sql).
Đọc bài viết →exercise_03_database_design.sql
exercise_03_database_design.sql — sql source code from the SQL learning materials (SQL/exercises/exercise_03_database_design.sql).
Đọc bài viết →exercise_04_database_functions.sql
exercise_04_database_functions.sql — sql source code from the SQL learning materials (SQL/exercises/exercise_04_database_functions.sql).
Đọc bài viết →01_database_setup.py
01_database_setup.py — python source code from the SQL learning materials (SQL/python_examples/01_database_setup.py).
Đọc bài viết →