Slide 1: SQL as a Declarative Language
SQL operates on a principle of describing what you want, rather than spelling out each computational step. This design philosophy makes SQL unique among programming languages - you declare your desired outcome, and the SQL engine determines the most efficient path to achieve it.
# Example showing declarative vs imperative approach
# Declarative (SQL-like) approach in Python
data = [
{'name': 'Alice', 'age': 25},
{'name': 'Bob', 'age': 30},
{'name': 'Charlie', 'age': 35}
]
# Using list comprehension (declarative-style)
adults = [person for person in data if person['age'] >= 30]
# Imperative approach
adults = []
for person in data:
if person['age'] >= 30:
adults.append(person)Slide 2: Query Structure
A SQL query follows a logical structure where clauses are arranged in a specific order. While written in one sequence, the execution follows a different path, optimizing for performance and data integrity.
def demonstrate_query_structure():
query = {
'select': ['column1', 'column2'],
'from': 'table_name',
'where': 'condition',
'group_by': 'column1',
'having': 'group_condition',
'order_by': 'column1',
'limit': 10
}
return querySlide 3: FROM and JOIN Operations
The first step in query execution involves identifying and combining data sources. This forms the foundation of all subsequent operations.
def demonstrate_join():
table1 = [('A', 1), ('B', 2), ('C', 3)]
table2 = [(1, 'X'), (2, 'Y'), (3, 'Z')]
# Simulating an INNER JOIN
joined_data = []
for t1 in table1:
for t2 in table2:
if t1[1] == t2[0]: # Join condition
joined_data.append((t1[0], t1[1], t2[1]))
return joined_dataSlide 4: WHERE Clause Processing
After data sources are combined, filtering occurs through the WHERE clause. This step eliminates rows that don't meet specified conditions.
def filter_data(data, condition):
# Simulating WHERE clause
return [
row for row in data
if eval(f"row[condition['column']] {condition['operator']} {condition['value']}")
]
# Example usage
data = [{'age': 25}, {'age': 30}, {'age': 35}]
condition = {'column': 'age', 'operator': '>', 'value': 30}
filtered = filter_data(data, condition)Slide 5: GROUP BY Implementation
The GROUP BY operation aggregates rows sharing common values, creating a foundation for aggregate functions.
from collections import defaultdict
def group_data(data, group_column):
groups = defaultdict(list)
for row in data:
key = row[group_column]
groups[key].append(row)
return dict(groups)
# Example data
data = [
{'category': 'A', 'value': 1},
{'category': 'B', 'value': 2},
{'category': 'A', 'value': 3}
]
grouped = group_data(data, 'category')Slide 5: GROUP BY Implementation
GROUP BY transforms individual rows into grouped sets based on specified columns, preparing data for aggregate operations like counting or averaging values.
def simple_group_by(data):
# Sample data representing colors and their occurrences
colors = ['red', 'blue', 'red', 'green', 'blue', 'red']
# Dictionary to store grouped counts
grouped_data = {}
# Group and count occurrences
for color in colors:
if color in grouped_data:
grouped_data[color] += 1
else:
grouped_data[color] = 1
return grouped_dataSlide 6: Results for GROUP BY Implementation
# Output of simple_group_by():
{
'red': 3,
'blue': 2,
'green': 1
}Slide 7: HAVING Clause
The HAVING clause filters grouped data based on aggregate conditions, operating after GROUP BY has formed the groups.
def apply_having(grouped_data, min_count):
# Filter groups based on count threshold
filtered_groups = {
color: count
for color, count in grouped_data.items()
if count >= min_count
}
return filtered_groups
# Usage example with minimum count of 2
result = apply_having({'red': 3, 'blue': 2, 'green': 1}, 2)Slide 8: SELECT Processing
SELECT determines which columns appear in the final output, possibly including calculated values or aggregate functions.
def process_select(data, columns):
# Sample data processing with SELECT-like behavior
selected_data = []
for record in data:
selected_record = {}
for col in columns:
if col in record:
selected_record[col] = record[col]
selected_data.append(selected_record)
return selected_dataSlide 9: ORDER BY Implementation
ORDER BY sorts the final result set based on specified columns and sort directions.
def custom_sort(data, sort_key, ascending=True):
# Implementation of basic sorting mechanism
sorted_data = sorted(
data,
key=lambda x: x[sort_key],
reverse=not ascending
)
return sorted_dataSlide 10: LIMIT Operation
LIMIT controls the number of rows in the final output, useful for pagination and reducing data volume.
def apply_limit(data, limit_value):
# Simple implementation of LIMIT
return data[:limit_value] if limit_value > 0 else dataSlide 11: Real-Life Example - Student Records
This example demonstrates a complete query execution flow using student attendance records.
def process_student_records():
# Sample student attendance data
records = [
{'student': 'Alice', 'subject': 'Math', 'attendance': 90},
{'student': 'Bob', 'subject': 'Math', 'attendance': 85},
{'student': 'Alice', 'subject': 'Science', 'attendance': 95}
]
# Group by student
grouped = {}
for record in records:
student = record['student']
if student not in grouped:
grouped[student] = []
grouped[student].append(record)
# Calculate average attendance per student
averages = {
student: sum(r['attendance'] for r in records) / len(records)
for student, records in grouped.items()
}
return averagesSlide 12: Real-Life Example - Weather Data Analysis
This example shows how to process and analyze temperature readings.
def analyze_temperature_readings():
# Sample temperature readings throughout a day
readings = [
{'hour': 1, 'temp': 20}, {'hour': 2, 'temp': 19},
{'hour': 3, 'temp': 18}, {'hour': 4, 'temp': 20}
]
# Group by temperature value
temp_groups = {}
for reading in readings:
temp = reading['temp']
if temp not in temp_groups:
temp_groups[temp] = []
temp_groups[temp].append(reading['hour'])
# Find most frequent temperature
most_frequent = max(temp_groups.items(), key=lambda x: len(x[1]))
return {
'temp': most_frequent[0],
'occurrences': len(most_frequent[1]),
'at_hours': most_frequent[1]
}Slide 13: Additional Resources
For deeper understanding of SQL query execution and optimization, refer to:
- "Query Optimization Techniques in Database Systems" (arXiv:1911.03834)
- "A Survey of Query Execution Engine and Query Optimization" (arXiv:2111.02668)