The Ultimate SQL Crash Course to Ace Your Next Interview
SQL (Structured Query Language) has long been the lingua franca of data analysis and database management. But in recent years, with the explosive growth of big data and the rise of artificial intelligence and machine learning, SQL has taken on new importance.
According to a 2020 Kaggle survey of data professionals, SQL is the most commonly used programming language, with 74% of respondents reporting using it regularly. And in a 2021 survey by Burtch Works, 61% of data scientists and analytics professionals rated SQL as the most important skill for job seekers in their field.
So whether you‘re a seasoned data professional or a new entrant to the field of AI/ML, a solid grasp of SQL is essential. In this guide, we‘ll dive deep into 5 of the most common and important SQL concepts covered in interviews. Along the way, we‘ll explore real-world examples and discuss best practices through the lens of AI and machine learning.
Here‘s what we‘ll cover:
- SQL vs MySQL: What‘s the difference and why does it matter?
- JOINs in SQL: A comprehensive guide with examples
- WHERE vs HAVING: When to use each clause for filtering
- Finding the 2nd highest salary: A classic SQL interview problem
- Indexes in SQL: The key to optimizing query performance
Let‘s get started!
1. SQL vs MySQL in the Age of Cloud Computing and Big Data
One of the first points of confusion for many SQL learners is the difference between SQL and MySQL. While often used interchangeably, they are distinct concepts:
- SQL is a language for querying and manipulating relational databases
- MySQL is a specific relational database management system (RDBMS) that uses SQL
MySQL is just one of many RDBMSs, alongside others like PostgreSQL, Oracle, and Microsoft SQL Server. Here‘s a comparison of some key characteristics:
| RDBMS | Developer | OS | Licenses | Relative Performance |
|---|---|---|---|---|
| MySQL | Oracle | Cross-platform | GPL or commercial | Good for most use cases |
| PostgreSQL | Open source | Cross-platform | Open source | Best performance overall |
| Oracle | Oracle | Cross-platform | Commercial | Fastest for complex queries |
| SQL Server | Microsoft | Windows only | Commercial | Best integration with Windows |
In recent years, cloud computing has dramatically changed the landscape of SQL databases. Cloud providers like Amazon Web Services, Google Cloud, and Microsoft Azure all offer managed SQL database services, such as Amazon RDS, Cloud SQL, and Azure SQL Database. These services abstract away much of the underlying infrastructure management, allowing developers to focus on their data and applications.
The rise of big data has also impacted the SQL ecosystem. Massively parallel processing databases like Amazon Redshift, Google BigQuery, and Snowflake have emerged to handle petabyte-scale datasets. These systems often use SQL as their query language, but with proprietary extensions and limitations.
In the realm of big data processing, SQL interfaces have become increasingly important. Apache Hive, for example, provides an SQL-like interface for querying data stored in Hadoop. Spark SQL allows querying structured data within Spark programs using SQL. These tools have made SQL an essential skill for data engineers and scientists working with large-scale datasets.
2. Joining Forces: A Deep Dive into SQL JOINs
JOINs are the backbone of SQL‘s ability to combine data from multiple tables. But with so many types of JOINs available, it can be daunting for beginners to know which to use when. Let‘s break it down.
The most common types of JOINs are:
- (INNER) JOIN: Returns only rows that match the join condition in both tables
- LEFT (OUTER) JOIN: Returns all rows from the left table, plus matching rows from the right table (non-matching rows have NULL values)
- RIGHT (OUTER) JOIN: The inverse of LEFT JOIN
- FULL (OUTER) JOIN: Returns all rows from both tables, filling in NULLs for non-matches
To illustrate, let‘s consider a simple e-commerce schema with two tables: orders and customers.
SELECT *
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.total > 100;
This query performs an inner join to combine rows from the orders and customers tables where the customer_id foreign key matches the id primary key, and the order total exceeds $100.
But what if we wanted to analyze all customers, including those who haven‘t made a purchase? We could use a LEFT JOIN:
SELECT c.name, SUM(o.total) AS lifetime_value
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.name;
This query calculates the lifetime value for each customer, including those with zero purchases.
JOINs are crucial for analytics and machine learning workloads, as they allow combining disparate data sources into denormalized tables for analysis. But on large datasets, JOINs can become a performance bottleneck. Some best practices:
- Filter tables before joining to reduce the data volume
- Use indexes on the join keys to speed up the matching process
- Prefer INNER JOINs to OUTER JOINs where possible, as they are generally faster
When building machine learning models, JOINs are often used in the feature engineering process to create new input signals. For example, joining customer demographic data with their purchase history to predict future buying behavior.
3. Filtering with Finesse: WHERE vs HAVING
Another common point of SQL confusion is the difference between the WHERE and HAVING clauses. Both are used to filter data, but they operate at different stages in the query execution process.
The WHERE clause is used to filter individual rows before any grouping or aggregation takes place. For example:
SELECT *
FROM employees
WHERE salary > 50000;
This query returns all rows from the employees table where the salary exceeds $50,000.
The HAVING clause, on the other hand, is used to filter groups after aggregation. It‘s commonly used with the GROUP BY clause:
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 75000;
This query returns the average salary for each department, but only for departments where the average exceeds $75,000.
One way to think about it is that WHERE is applied to the raw data, while HAVING is applied to the aggregated results. A common mistake is to try to use HAVING to filter on non-aggregated columns, which will result in an error.
From a performance perspective, filtering with WHERE is generally more efficient than HAVING, because it reduces the amount of data that needs to be aggregated. However, there are cases where HAVING is necessary, such as when filtering on an aggregate function like COUNT or SUM.
When writing complex queries, it‘s often helpful to use both WHERE and HAVING together. For example:
SELECT department, AVG(salary) AS avg_salary
FROM employees
WHERE hire_date > ‘2020-01-01‘
GROUP BY department
HAVING AVG(salary) > 75000;
This query first filters the employees to only those hired after January 1, 2020, then groups by department and filters only those departments with an average salary above $75,000.
4. Climbing the Salary Ladder: Finding the Second Highest Salary
A classic SQL interview question is to find the second highest salary in an employees table. This problem tests your understanding of subqueries and aggregate functions.
Given this table:
+----+-------+--------+
| id | name | salary |
+----+-------+--------+
| 1 | Alice | 100000 |
| 2 | Bob | 99000 |
| 3 | Carol | 98000 |
| 4 | David | 97000 |
| 5 | Eve | 96000 |
| 6 | Frank | 99000 |
+----+-------+--------+
One solution is to use a subquery to find the maximum salary, then find the maximum salary less than that value:
SELECT MAX(salary) AS second_highest_salary
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);
This query first finds the overall maximum salary (100000), then finds the maximum salary that‘s less than that value (99000).
An alternative solution is to use the DENSE_RANK() window function:
SELECT salary AS second_highest_salary
FROM (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) t
WHERE rnk = 2;
This query assigns a rank to each salary in descending order, then selects the salary with rank 2.
The key difference is that the subquery solution will return NULL if there is no second highest salary (e.g. if there are less than two distinct salaries), while the window function solution will return the highest salary in that case.
In terms of performance, both solutions require scanning the entire table, so they have similar time complexity of O(n). However, the window function solution is generally more readable and extensible (e.g. it‘s easy to find the Nth highest salary by changing the rank filter).
This type of problem is similar to other common coding interview questions like finding the Kth largest element in an array. The key is to break the problem down into smaller subproblems and use the tools available (in this case, SQL‘s built-in functions and subqueries) to solve them.
5. The Need for Speed: SQL Indexes Explained
As data volumes grow, the importance of optimizing SQL query performance becomes paramount. One of the most powerful tools in the SQL optimization toolbox is the index.
An index is a data structure that allows the database to quickly locate rows matching a given condition without scanning the entire table. Indexes are built on one or more columns of a table and store a sorted copy of those columns‘ values along with pointers to the corresponding rows.
There are two main types of indexes in SQL:
-
Clustered Index: This determines the physical order of the data in the table. Each table can have only one clustered index. In MySQL‘s InnoDB storage engine, the primary key is the clustered index.
-
Non-Clustered Index: This is a separate structure from the table data. Each value in the index contains a pointer to the corresponding row in the table. A table can have multiple non-clustered indexes.
The choice of which columns to index is a crucial factor in query performance. Some guidelines:
- Index columns used frequently in WHERE, JOIN, and ORDER BY clauses
- Avoid indexing columns with few unique values or many NULL values
- Consider composite indexes for queries that filter on multiple columns
To illustrate the impact of indexes, consider a query to find all users with a specific email domain:
SELECT *
FROM users
WHERE email LIKE ‘%@gmail.com‘;
Without an index on the email column, this query would require a full table scan, which could be very slow for a large table. But with an index, the database can quickly locate the rows matching the email pattern.
It‘s important to note that while indexes can dramatically improve read performance, they come at a cost for write operations. Every time a row is inserted, updated, or deleted, any indexes on that table must be updated as well. Therefore, it‘s important to strike a balance and not over-index tables.
Some database systems, like MySQL, use a cost-based optimizer to choose the most efficient execution plan for a query based on available indexes and statistics about the data. Understanding how the optimizer works can help in designing effective indexes.
In the world of big data, indexing becomes even more critical. Many distributed SQL query engines, like Presto and Drill, rely heavily on partitioning and indexing to enable efficient querying of large datasets.
As AI and machine learning workloads increasingly require real-time querying of massive datasets, optimizing SQL performance through effective indexing will be a key skill for data professionals.
The Future of SQL in an AI-Driven World
As we‘ve seen, SQL is a critical skill for anyone working with data, and its importance is only growing in the age of artificial intelligence and machine learning.
While the rise of unstructured data and NoSQL databases has led some to question the relevance of SQL, the reality is that structured data still powers much of the world‘s data infrastructure. And as data volumes continue to grow, the need for efficient, scalable querying becomes ever more important.
In fact, many of the largest tech companies, like Google, Facebook, and Airbnb, rely heavily on SQL-based systems for their data warehousing and analytics needs. And with the growth of cloud-based data warehouses like Snowflake and BigQuery, SQL skills are in high demand.
For aspiring data professionals, learning SQL is a great place to start. But to truly excel in the field, it‘s important to go beyond the basics and develop a deep understanding of query optimization, indexing, and performance tuning.
Some next steps to consider:
- Dive into the internals of your database system of choice, whether it‘s MySQL, PostgreSQL, or a cloud-based system like Redshift or BigQuery
- Experiment with real-world datasets and practice optimizing queries for performance
- Learn about distributed SQL query engines like Presto and Spark SQL
- Explore the intersection of SQL and machine learning through technologies like BigQuery ML and Amazon Athena
With a solid foundation in SQL and a commitment to continuous learning, you‘ll be well-positioned for a successful career in data science, analytics, and AI/ML.