SQL Interview Preparation Guide
SQL Interview Preparation Guide
SQL INTERVIEW
PREPARATION
HANDBOOK
FROM BASICS TO ADVANCED
[Link]
Amr Abdelkarem 02
A:
CHAR stores fixed-length data and pads unused space
with blanks.
VARCHAR2 stores variable-length data and uses only the
required space.
Example:
CHAR(10) with 'SQL' →
10 bytes
VARCHAR2(10) with 'SQL' →3 bytes
[Link]
Amr Abdelkarem 03
A:
A view is a virtual table created from a SELECT query.
It doesn’t store data but displays data from one or more
tables.
Views make complex queries simpler, improve readability, and
enhance security by limiting access to certain rows or
columns.
Example:
[Link]
Amr Abdelkarem 04
A:
The UNIQUE constraint ensures that all values in a column or a
group of columns are distinct.
It prevents duplicate entries and maintains data integrity.
Example:
[Link]
Amr Abdelkarem 05
A:
A composite primary key combines two or more columns to
uniquely identify each record when a single column cannot do
so.
Example:
[Link]
Amr Abdelkarem 06
A:
WHERE filters individual rows before grouping or
aggregation. It cannot use aggregate functions like SUM or
COUNT.
HAVING filters grouped results after GROUP BY. It is used for
conditions involving aggregate functions.
Example:
[Link]
Amr Abdelkarem 07
Example:
[Link]
Amr Abdelkarem 08
A:
PRIMARY KEY uniquely identifies each row in a table. It
enforces both UNIQUE and NOT NULL. Only one primary key
is allowed per table, but it can span multiple columns. It’s
commonly referenced by foreign keys.
UNIQUE Key also enforces uniqueness but allows NULL
values. Multiple unique constraints can exist in the same
table.
Example:
[Link]
Amr Abdelkarem 09
A:
A CTE is a temporary named result set created using the WITH
clause. It exists only during the execution of one SQL
statement.
You use CTEs to:
Simplify complex queries by breaking them into steps
Avoid repeating subqueries
Improve readability and maintainability
Support recursive queries like organization charts or folder
hierarchies
Example:
[Link]
Amr Abdelkarem 10
[Link]
Amr Abdelkarem 11
Example (UNION):
[Link]
Amr Abdelkarem 12
Example:
[Link]
Amr Abdelkarem 13
Example:
[Link]
Amr Abdelkarem 14
Example:
[Link]
Amr Abdelkarem 15
Use Case:
Find employees whose salary is above their department’s
average.
Example:
[Link]
Amr Abdelkarem 16
Key Differences:
EXISTS and NOT EXISTS use correlated subqueries and
handle NULL safely.
NOT IN is sensitive to NULL values and may produce no
results if any NULL exists in the list.
EXISTS generally performs better on large subqueries with
indexes, while IN is better for small lists.
Example:
[Link]
Amr Abdelkarem 17
Q: What is an anti-join?
A:
An anti-join returns rows from one table that have no
corresponding matches in another table. It identifies records
that exist in one dataset but not in the other.
[Link]
Amr Abdelkarem 18
Example:
[Link]
Amr Abdelkarem 19
A:
LAG and LEAD are window functions used to access values
from previous or next rows within the same result set. They
help compare values across rows without using self-joins.
Use Cases:
Track changes between consecutive rows (e.g., day-to-
day sales difference)
Detect trends or anomalies over time
Fill missing values using data from adjacent rows
Example:
[Link]
Amr Abdelkarem 20
Example:
[Link]
Amr Abdelkarem 21
Example:
[Link]
Amr Abdelkarem 22
Example:
[Link]
Amr Abdelkarem 23
[Link]
Amr Abdelkarem 24
A:
A query is a SQL command used to retrieve, insert, update, or
delete data in a database.
The most common type is the SELECT query, which fetches
data from one or more tables based on defined conditions.
Example:
[Link]
Amr Abdelkarem 25
Q: What is a subquery?
A:
A subquery is a query embedded inside another SQL query. It
returns a result that the outer query uses for filtering,
comparison, or computation.
Subqueries are commonly used in WHERE, FROM, or SELECT
clauses to handle complex filtering or calculations.
Example:
[Link]
Amr Abdelkarem 26
A:
Database partitioning divides a large table and its indexes
into smaller, more manageable parts called partitions while
keeping it logically as one table.
Benefits:
Improves query performance by scanning only relevant
partitions (partition pruning).
Simplifies maintenance tasks such as backup, reindexing,
and archiving.
Increases availability by isolating failures or heavy
operations to specific partitions.
[Link]
Amr Abdelkarem 27
Key Strategies:
Parameterized queries (prepared statements): Always
bind parameters instead of concatenating strings.
Input validation: Allow only expected patterns (e.g., digits
for IDs, fixed enums for status).
Least privilege: Use database accounts with only
necessary permissions (no DROP, limited schema access).
Safe stored procedures: Avoid building dynamic SQL inside
procedures.
Escaping and ORM frameworks: Use database libraries or
ORMs that automatically escape input and enforce safe
query patterns.
Example (Python):
[Link]
Amr Abdelkarem 28
A:
SQL commands are grouped by their purpose in managing
data and structure.
DDL (Data Definition Language): Defines and modifies
database objects.
CREATE, ALTER, DROP, TRUNCATE
DML (Data Manipulation Language): Manages data inside
tables.
SELECT, INSERT, UPDATE, DELETE
DCL (Data Control Language): Controls access and
permissions.
GRANT, REVOKE
TCL (Transaction Control Language): Manages
transactions and ensures consistency.
COMMIT, ROLLBACK, SAVEPOINT
[Link]
Amr Abdelkarem 29
A:
The DEFAULT constraint assigns a predefined value to a
column when no value is specified during an INSERT. It ensures
consistency and simplifies data entry.
Example:
[Link]
Amr Abdelkarem 30
A:
Denormalization combines normalized tables into fewer, larger
tables to improve query performance. It trades some
redundancy for faster reads.
When to Use:
When frequent joins cause slow performance.
In reporting or analytics systems focused on read-heavy
workloads.
When data is mostly static and consistency risks are
manageable.
Example:
Merging orders and customers into a single table to avoid
joining during reporting.
[Link]
Amr Abdelkarem 31
Example:
[Link]
Amr Abdelkarem 32
Example:
[Link]
Amr Abdelkarem 33
Example:
This query returns one row per department with the total
number of employees and their average salary.
[Link]
Amr Abdelkarem 34
Example:
[Link]
Amr Abdelkarem 35
Trade-offs:
Consume extra storage.
Slow down INSERT, UPDATE, and DELETE operations due to
index maintenance.
Types of Indexes:
Clustered Index: Physically sorts data by the key (one per
table).
Non-Clustered Index: Separate structure pointing to data
rows (many allowed).
Unique Index: Ensures all values are distinct.
Composite Index: Built on multiple columns for combined
lookups.
[Link]
Amr Abdelkarem 36
Example:
[Link]
Amr Abdelkarem 37
SQL Databases:
Store data in structured tables with rows and columns.
Use a fixed schema.
Support ACID (Atomicity, Consistency, Isolation, Durability)
transactions.
Best suited for complex queries and relationships.
Examples: MySQL, PostgreSQL, Oracle, SQL Server.
NoSQL Databases:
Store data in flexible, schema-less formats (key-value,
document, column, graph).
Scale horizontally across many servers.
Often prioritize availability and scalability over strict
consistency (BASE model).
Ideal for large volumes of unstructured or rapidly changing
data.
Examples: MongoDB, Cassandra, Redis, DynamoDB.
[Link]
Amr Abdelkarem 38
A:
Constraints define rules to maintain accuracy and
consistency of data in a table.
Main Types:
NOT NULL: Prevents a column from storing NULL values.
UNIQUE: Ensures all values in a column are distinct.
PRIMARY KEY: Uniquely identifies each row (implies UNIQUE
+ NOT NULL).
FOREIGN KEY: Maintains referential integrity by referencing
another table’s key.
CHECK: Ensures values meet a specific condition.
DEFAULT: Assigns a predefined value when no value is
provided.
Example:
[Link]
Amr Abdelkarem 39
Example:
[Link]
Amr Abdelkarem 40
Types:
BEFORE Trigger: Executes before the triggering event.
AFTER Trigger: Executes after the event completes.
Common Uses:
Enforcing business rules (e.g., preventing invalid updates).
Maintaining audit logs.
Validating or transforming data automatically.
Example:
[Link]
Amr Abdelkarem 41
Example:
[Link]
Amr Abdelkarem 42
Example:
[Link]
Amr Abdelkarem 43
Example:
[Link]
Amr Abdelkarem 44
Key Points:
Comparisons using = or != with NULL return unknown; use
IS NULL or IS NOT NULL instead.
Aggregate functions ignore NULL values unless specified
otherwise.
Example:
[Link]
Amr Abdelkarem 45
Benefits:
Improves performance by avoiding repeated parsing and
compilation.
Centralizes business logic for easier maintenance.
Enhances security by controlling direct access to tables.
Example:
[Link]
Amr Abdelkarem 46
[Link]
Amr Abdelkarem 47
Common Uses:
Add or drop columns.
Change a column’s data type or size.
Add or remove constraints.
Rename columns or tables.
Modify indexing or storage settings.
Example:
[Link]
Amr Abdelkarem 47
[Link]
Amr Abdelkarem 48
Example:
[Link]
Amr Abdelkarem 49
Example:
[Link]
Amr Abdelkarem 50
Example:
[Link]
Amr Abdelkarem 51
COUNT():
Counts the number of rows or non-NULL values in a column.
SUM():
Calculates the total of numeric values in a column.
Key Difference:
COUNT() measures quantity (rows), while SUM() measures
total value (numeric data).
[Link]
Amr Abdelkarem 52
NVL(expr1, expr2)
Replaces NULL in expr1 with expr2.
Key Difference:
NVL handles a single replacement for NULL.
NVL2 lets you define separate values for both NULL and
non-NULL cases.
[Link]
Amr Abdelkarem 53
A:
Scalar functions operate on a single input value and return
one output value. They’re often used to format, transform, or
compute data at the column or row level.
Example:
[Link]
Amr Abdelkarem 54
A:
COUNT(column) ignores NULL values — it only counts rows
where the column has a non-NULL value.
COUNT(*) counts all rows, including those with NULL values
in any column.
Example:
[Link]
Amr Abdelkarem 55
Common Uses:
Ranking rows (RANK(), DENSE_RANK(), ROW_NUMBER())
Aggregates over partitions (SUM(), AVG(), COUNT())
Accessing neighboring rows (LAG(), LEAD())
Each row shows its own data plus the cumulative total of all
preceding salaries.
[Link]
Amr Abdelkarem 56
2. Key
A key is a logical constraint that enforces data integrity and
relationships within tables.
PRIMARY KEY: Ensures each row is unique and not null.
FOREIGN KEY: Maintains referential integrity between tables.
UNIQUE KEY: Prevents duplicate values in a column.
Example:
Key Difference:
Index→ improves performance.
Key → enforces data integrity and relationships.
[Link]
Amr Abdelkarem 57
How It Helps:
Reduces full table scans and disk I/O.
Speeds up WHERE, JOIN, ORDER BY, and GROUP BY
operations.
Enhances query response time on large datasets.
Example:
[Link]
Amr Abdelkarem 58
Advantages:
Speeds up SELECT queries, especially those using WHERE,
JOIN, or ORDER BY.
Improves sorting and filtering performance.
Reduces overall query execution time for large datasets.
Disadvantages:
Consumes additional storage for index structures.
Slows down INSERT, UPDATE, and DELETE operations since
indexes must be updated with every data change.
Makes bulk inserts and batch loads slower due to index
maintenance.
Summary:
Indexes improve read performance but increase storage
needs and write overhead. The right balance depends on
whether your workload is read-heavy or write-heavy.
[Link]
Amr Abdelkarem 59
[Link]
Amr Abdelkarem 60
Key Difference:
Standard View: Real-time, always current, slower for large
queries.
Materialized View: Cached data, faster access, needs
manual or scheduled refresh.
[Link]
Amr Abdelkarem 61
Key Features:
Auto-increments independently of any table.
Can define start value, increment step, and limits.
Ensures uniqueness without locking the table.
Example:
[Link]
Amr Abdelkarem 62
1. Greater Flexibility
Can define start value, increment, minimum, and
maximum limits.
Work as independent objects that can be shared across
multiple tables.
2. Dynamic Adjustment
Can alter sequence properties (e.g., restart value or
increment) without changing the table schema.
3. Cross-Table Consistency
One sequence can generate unique IDs for several related
tables, ensuring no duplication across them.
Summary:
Sequences provide more control, configurability, and
reusability than identity columns, which are tied to a single
table.
[Link]
Amr Abdelkarem 63
Example:
[Link]
Amr Abdelkarem 64
Example:
[Link]
Amr Abdelkarem 65
Functions:
INSERT: Adds new rows that don’t exist in the target.
UPDATE: Modifies existing rows that match between source
and target.
DELETE: Removes rows from the target that meet specific
conditions.
Example:
Note:
While powerful, MERGE can introduce concurrency issues such
as race conditions in SQL Server if not handled carefully.
[Link]
Amr Abdelkarem 66
2. Using ROW_NUMBER()
Assigns a sequence number to each row within a partition,
then filters out duplicates.
Summary:
GROUP BY is simple and efficient for aggregate-based
deduplication.
ROW_NUMBER() provides more control over which record
to keep.
[Link]
Amr Abdelkarem 67
[Link]
Amr Abdelkarem 68
[Link]
Amr Abdelkarem 69
Use Case:
WITH (NOLOCK) can be helpful for read-only analytics or
reporting queries where absolute accuracy isn’t critical, but it
should be avoided in transactional or financial operations
where data integrity matters.
[Link]
Amr Abdelkarem 70
[Link]
Amr Abdelkarem 71
Common Uses:
Reporting: Enables querying consistent, point-in-time data
without impacting the live database.
Backup and Recovery: Allows quick rollback to a previous state
after accidental changes or corruption.
Testing and Auditing: Provides a stable, unchanging dataset for
verification or test environments.
Key Point:
Snapshots are lightweight and fast for reads but cannot be updated.
They depend on the original database and grow as data changes.
[Link]
Amr Abdelkarem 72
[Link]
Amr Abdelkarem 73
1. Live Lock
Occurs when two or more transactions continuously react to
each other’s actions, preventing completion.
Transactions remain active but make no progress — they keep
retrying or yielding resources instead of completing.
Example: Two transactions repeatedly releasing and reacquiring
locks to avoid blocking, yet never finishing.
2. Deadlock
Occurs when two or more transactions hold resources the others
need, each waiting indefinitely for the other to release them.
All involved transactions are blocked until one is terminated.
Key Difference:
Deadlock: Transactions are stuck waiting.
Live Lock: Transactions are active but not progressing.
In both cases, no useful work is completed, but live locks involve
continuous activity, while deadlocks involve complete waiting.
[Link]
Amr Abdelkarem 74
Behavior:
Removes duplicates by default (like UNION).
Both queries must have the same number of columns with
compatible data types.
Example:
Use Cases:
Finding discrepancies between datasets.
Checking for records that exist in one table but not another.
Performance Note:
Efficient when both datasets are indexed; large unindexed tables
can slow performance due to full comparisons.
[Link]
Amr Abdelkarem 75
Best Practice:
Use sp_executesql with parameterization to mitigate SQL injection
and improve execution plan reuse.
[Link]
Amr Abdelkarem 76
Horizontal Partitioning:
Divides the rows of a table into multiple partitions based on
values in a specific column.
Example: Splitting a customer table into separate partitions by
geographic region or by year.
Use Case: When dealing with large datasets, horizontal
partitioning can improve performance by limiting the number of
rows scanned for a query.
Vertical Partitioning:
Divides the columns of a table into multiple partitions.
Example: Storing infrequently accessed columns (e.g., large text
or binary fields) in a separate table or partition.
Use Case: Helps in optimizing storage and query performance by
separating commonly used columns from less frequently
accessed data.
Key Difference:
Horizontal partitioning is row-based, focusing on distributing the
dataset’s rows across partitions.
Vertical partitioning is column-based, aiming to separate less-
used columns into different partitions or tables.
[Link]
Amr Abdelkarem 77
1. Indexing Strategy
Prioritize columns used in WHERE, JOIN, and ORDER BY clauses.
Avoid over-indexing — every index consumes storage and slows
write operations.
2. Index Types
Clustered Index: Best for primary key and range-based queries.
Non-Clustered Index: Improves filtering and sorting on non-key
columns.
Use covering indexes to include all columns a query needs.
3. Partitioned Indexes
For partitioned tables, create local indexes per partition.
Speeds up queries that target specific partitions.
Simplifies maintenance and parallel operations.
4. Maintenance Overhead
Regularly monitor fragmentation and rebuild or reorganize
indexes during off-peak hours.
Consider online index rebuilds to avoid blocking.
Reassess indexing needs as data volume and query patterns
evolve.
Summary:
Effective indexing of large tables focuses on the most beneficial
columns, minimizes write overhead, and uses partitioning and
maintenance strategies to sustain long-term performance.
[Link]
Amr Abdelkarem 78
1. Sharding
Splits a database into multiple independent databases (shards).
Each shard holds a subset of the data and operates on its own
server.
Aimed at horizontal scaling across multiple machines.
Used to handle very large datasets and high query loads.
Example: A global users database divided by region — one shard
for North America, another for Europe, another for Asia.
Key Benefit: Distributes load across servers, improving scalability
and fault isolation.
2. Partitioning
Divides a single table or database into smaller, logical pieces.
All partitions remain within the same database instance.
Aimed at performance optimization and maintenance efficiency.
Example: A sales table partitioned by year so that queries for
recent sales skip older partitions.
Key Benefit: Reduces query scan size, simplifies maintenance,
and improves data management.
Key Difference:
Sharding: Distributes data across multiple databases or servers
(horizontal scaling).
Partitioning: Organizes data within a single database
(performance and management optimization).
[Link]
Amr Abdelkarem 79
Examples:
[Link]
Amr Abdelkarem 80
[Link]
Amr Abdelkarem 81
[Link]
Amr Abdelkarem 82
Key Components:
Anchor Member: The initial query that starts the recursion.
Recursive Member: A query that references the CTE to
continue building the result set.
Termination Condition: Ensures that recursion stops after a
certain depth or condition is met.
Example:
[Link]
Amr Abdelkarem 83
Key Difference:
Transactional queries keep operational systems running
efficiently. Analytical queries extract insights and patterns
from large data volumes to support strategic decisions.
[Link]
Amr Abdelkarem 84
1. Distributed Transactions
Use a two-phase commit (2PC) protocol so that all databases either
commit or roll back together. This guarantees atomicity but can
reduce performance and scalability.
2. Eventual Consistency
Adopt eventual consistency when strict synchronization isn’t
required. Data updates propagate asynchronously and converge to
a consistent state over time, improving availability.
3. Conflict Resolution
Apply versioning, timestamps, or last-write-wins rules to detect and
resolve data conflicts when multiple nodes update the same record.
Summary:
Choose between strong consistency (2PC) and eventual consistency
based on system needs. Combine replication, conflict handling, and
regular validation to keep distributed data accurate and reliable.
[Link]
Amr Abdelkarem 85
How It Works:
1. The inner query selects the base data.
2. The PIVOT operator aggregates values (using SUM, AVG, etc.)
based on the specified column.
3. Each unique value in the pivot column becomes a new column in
the result set.
Use Case:
Ideal for turning transactional data into cross-tab reports, such as
displaying months, years, or categories as columns.
[Link]
Amr Abdelkarem 86
Bitmap Index
Represents each distinct column value as a bit array (bitmap).
Each bit corresponds to a row and indicates whether the row has
that value.
Performs fast logical operations (AND, OR, NOT) across columns.
Best for low-cardinality columns such as gender, status, or
yes/no fields.
B-tree Index
Stores data in a balanced tree where keys are sorted and linked
to their corresponding rows.
Allows quick lookups, inserts, and range scans.
Best for high-cardinality columns like IDs, timestamps, or prices.
Key Difference
Bitmap indexes are optimized for few distinct values and boolean
filtering.
B-tree indexes are optimized for unique or wide-ranging data
and range queries.
Example Use:
Bitmap index on is_active for fast filtering of true/false values.
B-tree index on order_date for efficient range queries over time.
[Link]