Technology - Non SAP

SQL Fundamentals — The Queries That Cover Most of What You Need

SQL has been around since 1974. It has outlasted dozens of technologies that were supposed to replace it. Today it is the language behind almost every relational database — Oracle, SQL Server, PostgreSQL, MySQL, SQLite, SAP HANA — and understanding it is one of those skills that quietly pays off in almost every technical role.

This post covers the core of SQL — the statements and concepts that cover the vast majority of real-world queries. Not every edge case, not every dialect difference — the foundation that makes everything else make sense.

What SQL is

SQL — Structured Query Language — is the standard language for interacting with relational databases. It lets you retrieve, insert, update and delete data, and define the structure of the database itself.

SQL categoryWhat it coversExamples
DQL — Data Query LanguageReading dataSELECT
DML — Data Manipulation LanguageInserting, updating, deleting dataINSERT, UPDATE, DELETE
DDL — Data Definition LanguageDefining tables and structureCREATE, ALTER, DROP
DCL — Data Control LanguagePermissions and accessGRANT, REVOKE

This post focuses on DQL — reading data with SELECT. That is what most people need most of the time, and it is the foundation for everything else.

The SELECT statement — where everything starts

Every SQL query that reads data starts with SELECT. The basic structure is always the same:

SELECT column1, column2

FROM table_name;

Let us use a real example. Say you have an Orders table:

order_idcustomer_nameamountstatuscountry
1001Rakesh Narayan1249.99confirmedFinland
1002Anna Korhonen340.00pendingFinland
1003Marco Bianchi875.50confirmedItaly
1004Sophie Dupont120.00cancelledFrance
1005Lars Eriksson2100.00confirmedSweden

SELECT customer_name, amount

FROM orders;

Returns: the customer_name and amount columns for every row in the table.

SELECT *

FROM orders;

The asterisk * means all columns. Use it for exploration — avoid it in production queries where you should name only the columns you need.

WHERE — filtering rows

WHERE filters which rows are returned. Only rows where the condition is true are included.

SELECT customer_name, amount

FROM orders

WHERE status = ‘confirmed’;

Returns only the three confirmed orders — Rakesh, Marco, Lars.

OperatorMeaningExample
=Equal tostatus = ‘confirmed’
!= or <>Not equal tostatus != ‘cancelled’
> / <Greater / less thanamount > 1000
>= / <=Greater or equal / less or equalamount >= 340
BETWEENWithin a range (inclusive)amount BETWEEN 100 AND 1000
INMatches any value in a listcountry IN (‘Finland’, ‘Sweden’)
LIKEPattern match — % is wildcardcustomer_name LIKE ‘R%‘
IS NULLValue is emptydelivery_date IS NULL
AND / ORCombine multiple conditionsstatus = ‘confirmed’ AND amount > 500

SELECT customer_name, amount, country

FROM orders

WHERE status = ‘confirmed’

AND amount > 500;

Returns: Rakesh (1249.99) and Lars (2100.00) — confirmed orders over 500.

ORDER BY — sorting results

SELECT customer_name, amount

FROM orders

ORDER BY amount DESC;

Returns all orders sorted by amount, highest first. Use ASC for ascending (default), DESC for descending.

GROUP BY and aggregate functions

GROUP BY collapses rows that share a value into a single row, letting you calculate totals, counts and averages per group.

FunctionWhat it returnsExample
COUNT(*)Number of rowsCOUNT(*) — count of orders
SUM(col)Total of a numeric columnSUM(amount) — total order value
AVG(col)Average of a numeric columnAVG(amount) — average order value
MAX(col)Highest valueMAX(amount) — largest order
MIN(col)Lowest valueMIN(amount) — smallest order

SELECT country,

COUNT(*) AS order_count,

SUM(amount) AS total_value

FROM orders

WHERE status != ‘cancelled’

GROUP BY country

ORDER BY total_value DESC;

This query returns: for each country, how many non-cancelled orders exist and their total value — sorted by value descending. A real reporting query.

💡 HAVING vs WHERE

WHERE filters rows before grouping. HAVING filters groups after aggregation. Example: HAVING SUM(amount) > 1000 — only return groups where the total is over 1000. You cannot use WHERE to filter on an aggregate — that is what HAVING is for.

JOIN — combining tables

Almost all real databases have data spread across multiple tables. JOIN is how you bring them together in a single query.

SQL JOIN types diagram showing four Venn diagrams for INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL OUTER JOIN

JOIN typeReturnsMost common?
INNER JOINOnly rows with a match in both tablesYes — the default in most queries
LEFT JOINAll rows from the left table, plus matching rows from the right. NULL where no match.Yes — common for optional relationships
RIGHT JOINAll rows from the right table, plus matching rows from the left. NULL where no match.Less common — LEFT JOIN with tables reversed is equivalent
FULL OUTER JOINAll rows from both tables. NULL where no match on either side.Rare — specific use cases

A practical JOIN example. Say you have a Customers table:

SELECT c.customer_name,

c.email,

o.amount,

o.status

FROM customers c

INNER JOIN orders o ON c.customer_id = o.customer_id

WHERE o.status = ‘confirmed’;

This returns customer name, email and confirmed order details — combining data from two tables via a shared customer_id.

Subqueries — queries inside queries

A subquery is a SELECT statement nested inside another query. It lets you use the result of one query as input to another.

SELECT customer_name, amount

FROM orders

WHERE amount > (

SELECT AVG(amount) FROM orders

);

Returns orders where the amount is above the average order value — without you having to calculate the average separately first.

SQL in the SAP context

SQL is not an abstract concept for SAP professionals — it shows up directly in daily work.

Where you encounter SQL in SAPHow it appears
ABAP Open SQLABAP’s SQL dialect for querying SAP tables — SELECT FROM BKPF WHERE BUKRS = ‘1000’
SAP HANA Studio / DBeaverDirect SQL queries on HANA tables for analysis, debugging and data exploration
CDS ViewsCore Data Services are SQL-based view definitions — the foundation of SAP Fiori and OData APIs
SAP Analytics CloudCustom calculations and dimensions often require SQL-like expressions
SAP Data SphereSAP’s data fabric platform uses SQL for data modelling and transformations
BTP Data PipelinesSQL queries used in data flow tasks to transform and load data

💡 ABAP SQL vs standard SQL

ABAP Open SQL is a subset of standard SQL with SAP-specific syntax. Key differences: table and field names follow SAP naming conventions (MANDT, BUKRS), JOINs work but with some restrictions, and there is no GROUP BY in older ABAP — aggregates use LOOP AT instead. In S/4HANA, ABAP SQL has been extended significantly and CDS Views handle most complex query logic.

The SQL query execution order

This is something many people learn late and wish they had known earlier. SQL clauses are written in one order but executed in a different order.

Execution orderClauseWhat it does
1FROM / JOINIdentify the source tables and combine them
2WHEREFilter rows before grouping
3GROUP BYGroup rows by the specified column(s)
4HAVINGFilter groups after aggregation
5SELECTChoose which columns to return
6ORDER BYSort the final result
7LIMIT / TOPRestrict the number of rows returned

💡 Why this matters

You cannot use a SELECT alias in a WHERE clause — because WHERE is evaluated before SELECT. You cannot filter on an aggregate with WHERE — use HAVING because it runs after GROUP BY. Knowing the execution order explains most SQL errors instantly.

Quick reference — the core SQL

Statement / clausePurposeKey syntax
SELECTChoose columns to returnSELECT col1, col2 FROM table
WHEREFilter rowsWHERE amount > 500 AND status = ‘confirmed’
ORDER BYSort resultsORDER BY amount DESC
GROUP BYAggregate rows by a columnGROUP BY country
HAVINGFilter aggregated groupsHAVING SUM(amount) > 1000
INNER JOINReturn matching rows from both tablesJOIN table2 ON table1.id = table2.id
LEFT JOINReturn all rows from left tableLEFT JOIN table2 ON table1.id = table2.id
COUNT / SUM / AVGAggregate functionsSELECT COUNT(*), SUM(amount), AVG(amount)
LIKEPattern matchingWHERE name LIKE ‘R%‘
INMatch against a listWHERE country IN (‘FI’, ‘SE’, ‘IT’)
IS NULLCheck for empty valuesWHERE delivery_date IS NULL
LIMIT / TOPRestrict number of rowsLIMIT 10 (MySQL/PG) or TOP 10 (SQL Server)

What to take away

SQL is deceptively simple to start and genuinely deep to master. The fundamentals in this post — SELECT, WHERE, JOIN, GROUP BY and subqueries — cover the vast majority of what you will need for data exploration, integration work, report writing and system debugging.

In the SAP world specifically, ABAP SQL and CDS Views are built on these same foundations. Getting comfortable with standard SQL makes SAP’s data layer much easier to reason about.

🔗 Related posts on this site

JSON — From Zero to Confident — APIs return data in JSON; databases store the same data in tables. The two formats are complementary.
REST API Design Principles — REST APIs often expose data that is ultimately stored in and queried from relational databases.
SAP S/4HANA vs ECC — CDS Views, which are SQL-based, are central to the S/4HANA data model and Fiori app architecture.

Published on rakeshnarayan.com — Articles

URL: https://rakeshnarayan.com/articles/sql-fundamentals/