Mastering SQL for Data Engineering: Advanced Queries, Optimization, and Data Modeling Best Practices

Moses MorrisMoses Morris
12 min read

Advanced SQL for Data Engineering

Querying a database should be at your fingertips. This helps you perform ETL and EDA processes as a data engineer, analyst, or scientist. Data comes in various shapes, structures, and features, but it has to be transformed to be meaningful and important to use the data. Various concepts come in handy during the Data modelling phase. A data engineer can perform CRUD operations and tailor the data according to specified needs in a certain domain. Some of these concepts of operations include understanding joins, SQL functions, SQL methods, formulas, and many more.

We can not ignore how we query because...

All these remain a starting point for best practices when performing SQL queries. However, some operations, when not optimized, cause a lot of lag(slow/poor performance), complexity, failures, inaccuracy and are vulnerable to injection attacks when using the Data. Data engineers support data analysts and automate ETL workflow for them.

Why do we need to master SQL for Data Engineering?

How we query the database is very important. This will help with visualization and information delivery. We often rely on data-building tools to perform DML, DDL, TCL, and DCL operations. This risks the understanding of what is happening and what data we need for the data engineering process. Sometimes we even rely on ORM(Object Relational Model) and DBT(Data Build Tools) tools to query.

These are the advantages of being an SQL master.

1. Avoiding redundancy. - Helps avoid extracting or exploring similar data with repetitive tasks. We can query solid data and get data results that are not redundant. We often rely on indexing and creating keys(PRIMARY AND FOREIGN KEYS) that create a unique identity.

  • Indexing also improves Lookup speed. Formulas can be easily created to enhance good code. This prevents the repetition of SQL queries that may render your code complicated.

  • The use of Normalization Forms also minimizes redundancy. You can achieve this by separating a column that appears in many tables by creating a table for it.


-- Create Index
CREATE INDEX customerID 
ON orders(customer_id);
-- Create Primary Key
CREATE TABLE customer (
    customerID INT PRIMARY KEY,
    name VARCHAR(100)
);

-- Normalization and Foreign Keys
CREATE TABLE cities (
    cityID INT PRIMARY KEY,
    city_name VARCHAR(100)
);

CREATE TABLE customers (
    customerID INT PRIMARY KEY,
    name VARCHAR(100),
    cityID INT,
    FOREIGN KEY (cityID) REFERENCES cities(cityID)
);

2. Security Enhancement. - This helps prevent tampering with the results or actual data, reducing compromised responses. Sometimes, this comes in handy with the use of VIEWS in SQL querying. This also helps prevent injections by protecting our SQL queries. We foster the idea of using sub-queries within a query. This abstracts data that is private for use by the pipeline. We can also create temporary result sets using the WITH clause. - This also helps in common table expressions for modular SQL. This is most efficient in ETL Pipelines

  • Some cloud platforms double-check nested queries, store logs and the history of queries. They even encourage the Data engineer to partition data.
-- Create Views for Abstraction
CREATE VIEW active_users AS
SELECT customerID, name, 
FROM users
WHERE status = ‘Active’;
// You can CREATE VIEWS, MODIFY VIEWS, and DROP VIEWS

-- Use of WITH
WITH Total AS (
    SELECT customerID, SUM(amount) AS total_spent
    FROM sales
    GROUP BY customerID
)
SELECT c.name, s.total_spent
FROM customers c
JOIN Totals ON c.customerID = s.customerID
WHERE s.total_spent > 10000;

3. Optimization of Queries. - We can optimize the SQL queries we are making, thus reducing Lag. We can also make the queries efficient and accurate with the needed results. We also use the EXPLAIN function to understand and improve the query’s execution.

  • The use of a specified query is also very important. Do not use "SELECT * " but "SELECT name, age, etc." the rows you need. You can also specify using the WHERE or HAVING clause in your query. Please note that you can also avoid sub-queries by using RANK functions: when data modeling: RANK(), DENSE_RANK(), and ROW_NUMBER(). These help in pivoting and un-pivoting operations.

  • You can also use LEAD AND LAG to create dynamic SQL functions, creating room for recursive functions.

-- Use of EXPLAIN
EXPLAIN
SELECT customerID, name, status
FROM customers
WHERE city = ‘UK’;

-- Use of HAVING
SELECT   age, date   
COUNT(*) AS customerAges
FROM customers GROUP BY date
HAVING COUNT(*) > 3;


-- Use of RANK()
WITH ranking AS (  
SELECT     
DENSE_RANK() OVER(ORDER BY amount DESC,date) AS rank,     
orderID,     amount   
FROM orders 
) 
SELECT * FROM ranking WHERE rank < 4;
//We want top 3 orders 
//We would like them to be ranked according to the amount -the higher the amount, the bigger the order. Then, check the date. - The oldest order is ranked higher than the recent order.


-- Use ROW_NUMBER() //to rank customers by amount within each order
SELECT customerID, name, OrderID, amount,
       ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY amount DESC) AS rank
FROM customers;

Using indexing in your SQL queries also saves you a lot of optimization bottlenecks.

4. Data Accuracy. - We have Precise data, but we also need meaningful data. Sometimes SQL basic queries don’t give meaningful data as responses. This is a high risk when making multiple queries in a crucial app. Apps that need to be fast and reliable with real-time information. The use of LIMIT and DISTINCT in SQL helps solve this accuracy problem and reduce latency within large-scale apps.

  • When working with APIS or unending datasets, you look at this as pagination or memory saving. The lesser the limit of the query load, the accurate the data query.
-- Use of LIMIT
SELECT name FROM customers_large_table
ORDER BY date DESC
LIMIT 50 OFFSET 100;
//This also helps with performance boost

-- Use of DISTINCT
SELECT DISTINCT * FROM customers_large_table
ORDER BY date DESC
LIMIT 50 OFFSET 100;

While working with some applications, there is a use of WHERE clause with keywords like “IN”, “NOT IN”, and “BETWEEN” to show specific data queried.

5. Integrity of the Data. - This helps in maintaining the integrity of our SQL query. This preserves data integrity via logging and tracking of all SQL operations. We usually normalize data before querying it. We can also use this to remove unnecessary data from the query results. The use of clauses like ORDER BY and GROUP BY helps maintain the integrity of the visual representation of data.

-- Use of ORDER BY
SELECT orderID, customerID, amount, date
FROM orders
ORDER BY date ASC;

-- Use of GROUP BY
SELECT orderID, customerID, amount, date
FROM orders
ORDER BY amount DESC;

Another way of ensuring integrity in SQL is the use of the ADD CONSTRAINT clause

-- Use of ADD CONSTRAINT

ALTER TABLE orders
ADD CONSTRAINT CustomerID
FOREIGN KEY (customerID) REFERENCES customers(customerID);
//The creation of all orders in our database requires our customer to use a Foreign key. 
//If we don’t have a customer ID, no order details are being made or created.

When working with SQL Querying, you can GRANT and REVOKE various permissions given to the data engineer to perform on the data. This authorizes operations towards the Database.

6. Performance of Your Queries. - The increase of performance by only the data needed, especially when working with large sets of data. A data engineer who has mastered this is aware of methods, set operations, and functions(aggregate functions and window functions) used for operations like limiting, distinguishing, and partitioning the SQL query responses.

  • The use of SQL functions also helps limit slow performance. You can also look at the WITH clause functions in Optimization of queries*..*

  • We can have a look at numeric functions like SUM, AVG, and COUNT other than writing expressions and having operations in your SQL query.

  • Using string, date, and time functions to work on SQL queried data: functions like CONCAT, LENGTH, SUBSTRING, REPLACE, UPPER, LOWER, DATE, TIMESTAMP, DATEADD, DATEPART, and TIME. **We have looked at some clause functions in the above queries.

-- Use of SUM
SELECT SUM(amount) AS total
FROM orders;

-- Use of AVG
SELECT AVG(amount)
FROM orders
WHERE customerID=1;
//Get the average of the amount where a certain customer has ordered


-- Use of AVG
SELECT Count(*)
FROM orders
WHERE customerID=1;
//Get the number of orders made by a customer

Part of performance tuning best practices, is avoiding subqueries as much as possible. Also, the use of WHERE speeds filtering compared to HAVING.

7. Relationships within your Queries. - When you are mastering SQL queries, it is easy to create variable and reference points for your data project, often referred to as Entity Relationships Modelling. This helps you create relationships in your data modeling process that help you make well-informed SQL queries that increase not only performance but also security.

  • The use of JOINS helps structure relevant SQL query responses. They allow data to move in a flowchart kind of manner.
 -- Use of JOINS
SELECT *
FROM customers e
JOIN orders d ON e.customerID = d.customerID;
//selecting customer details of customers that have orders

Remember that there are several types of JOINS, namely LEFT JOIN, RIGHT JOIN, INNER JOIN, etc.

8. Scalability in SQL queries implementation. - Working with advanced SQL querying techniques saves you a lot of time. Good SQL queries create an excellent platform for growth. Large scaling apps need a good mastery of SQL.

  • Scalable solutions help a data engineer to focus on the most important things. This gives room for expandable SQL queries. You do not have to write other code if you are building another unit in the same system.

  • We design reusable SQL pipelines by modularizing logic. For efficient processing, many engines use parallelism under the hood. Additionally, we can use PARTITION BY in window functions to logically group data and compute metrics within each group.

-- Partition orders by order date
CREATE TABLE orders (
    orderID INT,
    date DATE,
    amount DECIMAL(8, 2)
)
PARTITION BY RANGE (YEAR(date)) (
    PARTITION p2024 VALUES LESS THAN (2024),
    PARTITION p2025 VALUES LESS THAN (2025)
);

Bonus: Sometimes, when working with enormous sets of data, a data engineer needs to focus on writing reusable code. Why is this? This improves the flow of data. The engineer understands this by brainstorming which data should frequently be used within the data pipeline. This also helps maintain a good SQL query flow. A good schema is created to prevent bottlenecks in the data pipelines created alongside various processes (EDA - Exploratory Data Analysis, ETL - Extract, Transform and Load). This schema can also have logging processes to help troubleshoot SQL failures within the application.

What is a data model? And why do we use our SQL mastery to achieve the best results when data modeling?

A data model is a visual representation of data interacting with the system. Data modelling is the process of interaction within the system. It involves defining and organizing data in a way that structures data to support the system’s functionality. It plays a significant role to a data engineer since it ensures accuracy, consistency, and efficiency. A model is developed to show relationships and how data moves across the system. UML diagrams and ER diagrams provide a visual representation of this.

A data model helps you write schema for the SQL. It lets you know which data interacts with which data and how each data flows in the system without compromising the integrity. Data governance is maintained at the highest level. It also gives control, regulation, authorization, and access methods that preserve data in the right state. Data is compromised if the source of the data is altered and hence can not be trusted. This provides unreliable insights. Some tools are like Microsoft Power BI, Tableau, Qlik Sense, and Looker used for visualization, reports and interactive dashboards.

Valuable concepts and practices for data engineers that help in advanced querying, optimizing and data modeling in SQL

Here are some concepts that make building, implementing, maintaining, and deploying pipelines a more masterly way: These are advanced SQL practices with examples.

1. Creating user-defined functions(UDF) - these are functions added in complex pipelines. These functions are created by the user depending on the domain of expertise the user is in. The data engineer documents the function and then uses it to make queries. They define the business logic and break complex queries into understandable tasks.

`-- Create reusable functions
CREATE FUNCTION calculateTax(amount DECIMAL)
RETURNS DECIMAL
BEGIN
  RETURN amount * 0.16;
END;`.

2. Creating Logging and Auditing for Queries - some queries create permanent changes to the database. Having a way to log or store action history is important. This helps the data engineer for trailing mistakes or progress made while querying. This helps in compliance in different domain expertise.

`-- Create a logging table
CREATE TABLE customerLog (
    logID INT AUTO_INCREMENT PRIMARY KEY,
    customerID INT,
    action VARCHAR(50),
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
    FOREIGN KEY (customerID) REFERENCES customers(customerID);
);
//On the Database end, you can also create event triggers on the Database used`.

3. Transaction Handling - A transaction is a query process that has to be completed to proceed to make changes within the SQL operation. These are Transaction Isolation Levels A COMMIT marks a successful end of a transaction, saving all changes made during the transaction permanently to the database.
A ROLLBACK cancels the transaction and undoes all changes made after the transaction began or up to a specified SAVEPOINT.
A BEGIN (or START TRANSACTION) indicates the beginning of a transaction block, allowing you to group multiple SQL statements as one atomic operation.
A SAVEPOINT creates a labeled point within a transaction to which you can later roll back without affecting the entire transaction. Ensures Atomicity and is used for critical data operations.

  • This can be used as a trick to only allow a complete transaction to make changes. This is where if an error occurs while a Query is running, the transaction is considered incomplete, hence a rollback (ROLLBACK). If no error occurs, the query can be completed and committed(COMMIT).
-- Create a Process that ensures ATOMICITY and Rollback safety.
BEGIN;
UPDATE orders SET amount = amount - 100 WHERE customerID = 1;
SAVEPOINT service_amount;
UPDATE orders SET  amount = amount + 100 WHERE customerID = 7;
-- Suppose something goes wrong with the second update
ROLLBACK TO service_amount;
-- Only the first update remains
COMMIT;

These concepts help the data engineer do data wrangling, reporting, and analyzing dashboards effectively and efficiently while maintaining quality data pipelines.

Conclusion

Mastering SQL is important to a data engineer. These are just a few concepts that will get you running as a master in SQL. In this data-driven world, this is to make sure you harness the superpower of being an SQL guru when working with data in your day-to-day operations. It makes your work more efficient, secure, and impactful. You can solve complex querying problems by having the above as a cheat sheet.

0
Subscribe to my newsletter

Read articles from Moses Morris directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Moses Morris
Moses Morris

Experienced software engineer with diverse skills in programming, web development, database management, and system administration.