SQL concepts from A to Z
Tags: data, database, sql, beginners
Published: 2019-02-06 08:17:15

---
title: SQL concepts from A to Z
published: true
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/xkbg7yt5hnkue2anx6dz.png
description: Terms and concepts if you need a refresher or have a junior analyst in your life who needs something to refer back to.
tags: #data, #databases, #sql, #beginner
---

It's time for some jargon-busting.

A big part of my role is to onboard and support junior data analysts. Many have just started using SQL, have come from the world of Excel analysis and have self-taught the SQL basics.

Here are some of those terms and concepts that pop up during training if you need a refresher or have a junior analyst in your life who needs something to refer back to.

------------------------

> [Alias](#chapter-1)
> [Begin Transaction](#chapter-2)
> [CTEs v Subqueries](#chapter-3)
> [Design](#chapter-4)
> [ETL](#chapter-5)
> [Function](#chapter-6)
> [Group By](#chapter-7)
> [Heaped Storage](#chapter-8)
> [Integrity](#chapter-9)
> [Join](#chapter-10)
> [Key](#chapter-11)
> [Lock](#chapter-12)
> [Massive Parallel Processing](#chapter-13)
> [Normalisation](#chapter-14)
> [OLTP v OLAP](#chapter-15)
> [Privileges](#chapter-16)
> [Query Plan](#chapter-17)
> [Disaster Recovery](#chapter-18)
> [System Tables](#chapter-19)
> [Truncate v Drop](#chapter-20)
> [Union](#chapter-21)
> [View](#chapter-22)
> [Window Function](#chapter-23)
> [XML](#chapter-24)
> [Year](#chapter-25)
> [Zero](#chapter-26)



--------------------

<a name="chapter-1"></a>
## Alias

When joining tables, we need to [state which column](https://docs.microsoft.com/en-us/sql/relational-databases/performance/joins?view=sql-server-ver15) from which table we want to match up, and which columns we want to return in the results. If there are columns with the same name we need to be specific about which column we want to return.

```sql
select
  orders.item, 
  inventory.item,
  inventory.unitprice
from 
  orders 
inner join 
  inventory 
on orders.order_item = inventory.inventory_item
```

To make it quicker to type we can alias the two tables with something shorter.

```sql
select
  o.item, 
  i.item,
  i.unitprice
from 
  orders o
inner join 
  inventory i 
on o.order_item = i.inventory_item
```

Instead of having to type out the whole table name each time we want a new column added, we can alias them with the letters 'o' for orders and 'i' for inventory.

Read more about JOINs and aliasing in this beginner-friendly post:

{% link https://dev.to/duomly/understand-sql-join-with-this-simple-tutorial-and-don-t-fail-as-i-did-2o5b %}

----------------------------

<a name="chapter-2"></a>
## Begin Transaction

[SQL Transactions](https://docs.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-locking-and-row-versioning-guide?view=sql-server-ver15) are used to trap errors when making changes to tables. During an UPDATE or DELETE statement, the change is auto-committed.

By wrapping the statement in a transaction we can 'roll back' or 'commit' when we are sure that it should be executed, or if a condition has been met.

The following transaction will run in a block and commit if successful.

```sql
begin transaction

update orders
set status = 'sent'
where order_id = '12345'

update orders
set status = 'sent'
where order_id = '54321'

commit transaction
```

Read more about how these work:

{% link https://dev.to/johndougherty68/database-transactions-like-youre-five-50i4 %}

----------------------------

<a name="chapter-3"></a>
## CTEs v Subqueries

[CTEs (Common Table Expressions)](https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver15) are a temporary, named result set we can come back to in the scope of a single SELECT, INSERT, UPDATE, DELETE or MERGE statement.

I use them when dealing with large tables for example: get all the columns I need from the 'emailsent' table, then get all the columns I need from the 'emailunsubscribe' table. Then in a final step join them together.

```sql
; -- start the CTE with a semicolon to terminate anything above

with sent as -- here is where you name the dataset

(select 
  emailaddress,
  emailid, 
  senddate
from
  marketing.emailsent
where
  senddate between '2018-01-01' and '2018-01-31'
),  -- add a comma if you need to add a subsequent CTE

unsubs as

(select 
  emailaddress,
  emailid, 
  senddate
from
  marketing.emailunsubscribe
where
  senddate between '2018-01-01' and '2018-01-31'
) -- no comma for the last CTE

select
  'January' as [monthdelivered],
  c.country, 
  count(distinct sent.emailaddress) as [countofdelivered], 
  count(distinct unsubs.emailaddress) as [countofunsubd]
from sent
left join 
  marketing.customers c on sent.email = unsubs.emailaddress
left join  
  unsubs on sent.email = unsubs.email 
  and sent.emailid = unsubs.emailid
```


[Chidiebere](https://dev.to/chidioguejiofor) has written an excellent series on CTEs and how they compare with the subquery.

{% link https://dev.to/chidioguejiofor/whats-with-cte-53ao %}


----------------------------

<a name="chapter-4"></a>
## Design

Star and snowflake schemas are made of two types of tables.

- Facts - that count how many times something has happened.
- Dimensions - (or Dims) that describe an attribute.

In the star model, we can have a sales table as our fact in the centre. Dimension tables for the store, product and location surround the fact like a star.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/in90kvm3zj8rm9sbuafw.png)

<center>*Attribution: SqlPac at English Wikipedia*</center>

The snowflake is similar but takes the dimensions one step further. Instead of just a location table, we may have a city, country and, postcode table. All the dimensions become the points on the snowflake.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pqjymxanga0jkl2qlt62.png)

<center>*Attribution: SqlPac at English Wikipedia*</center>

Read more about the advantages and disadvantages of both:

{% link https://dev.to/pedrojmfidalgopt/star-schema-vs-snowflake-schema-and-why-you-should-care-40fh %}



----------------------------

<a name="chapter-5"></a>
## ETL

ETL and ELT are the steps needed to move data from a source to a destination system.

- <strong>Extract</strong> - in the Extract step the raw data is moved from the source to a temporary or staging area.

- <strong>Transform</strong> - the Transform step converts the data to match the destination table. 

- <strong>Load</strong> - the Load step moves the data to its final destination for analysis or reporting.

ETL is great for putting data into the right format, stripping out unnecessary columns, and masking fields relating to GDPR compliance. 

However, ELT has become a more popular approach when used in conjunction with data lake architecture. The data arrives quickly as it does not have to be altered in any way. The Data Scientist can then use only the data needed, get results, and not deal with delays if a transformation step fails. 

Considerations need to be made around how reliable the data is in its raw form. Each Data Scientist or end-user should apply the same logic and business rules when analysing to keep results consistent.

For more on ETL, ELT and data pipelines check out this post from [SeattleDataGuy](https://dev.to/seattledataguy) who writes excellent posts on all things data.

{% link https://dev.to/seattledataguy/data-engineering-101-from-batch-processing-to-streaming-g91 %}


----------------------------

<a name="chapter-6"></a>
## Function

In PostgreSQL, we can execute blocks of code, called functions, on a schedule. They can be written like the statements we run ad hoc on the database or can be parsed variables to make them dynamic.

Read more about how to write and execute functions:

{% link https://dev.to/samuyi/a-primer-on-postgresql-stored-functions-plpgsql-1594 %}

----------------------------

<a name="chapter-7"></a>
## Group By

[Aggregate functions](https://docs.microsoft.com/en-us/sql/t-sql/functions/aggregate-functions-transact-sql?view=sql-server-ver15) allow us to perform calculations on fields. The most common ones are SUM, COUNT, MIN, MAX, AVERAGE.

For example, to see the total amount due for each item in the orders table we can use the SUM of the amount_due column and GROUP BY

```sql
select 
  order_item, 
  sum(amount_due) 
from orders
group by order_item;
```

Read more about Aggregate functions:

{% link https://dev.to/griffinator76/rollup-like-a-boss-3dkl %}

----------------------------

<a name="chapter-8"></a>
## Heaped Storage

Heaped storage is a term for tables that live on the database with no clustered index. The data is stored in no particular order and new data is added as it comes in.

Indexes are a way of telling the database to order the data or where to look to find the data you query often.

- <strong>Clustered Indexes</strong> are like the contents page of a book. Applying this kind of index is telling the data how it should be ordered, like the pages in a book.

![indexes1](https://thepracticaldev.s3.amazonaws.com/i/y7yo2tivweq1dsu763ie.PNG)

- <strong>Non-clustered Indexes</strong> are like the index of a book, the pages haven't been arranged that way physically, but you now have a lookup to get to what you need faster.

![indexes2](https://thepracticaldev.s3.amazonaws.com/i/cn0p49zsmec3x1zenlf5.PNG)

Read more in this beginner-friendly post:

{% link https://dev.to/mdgale/we-re-not-all-dbas-indexes-for-developers-557f %}

----------------------------

<a name="chapter-9"></a>
## Integrity

This refers to data quality and rules ensuring data is traceable, searchable and recoverable.

- Entity Integrity - each table must have a unique primary key
- Referential Integrity - foreign keys on each table refer to a primary key on another or is NULL
- Domain Integrity - each column has a specific data type and length.

Read more about integrity and database design:

{% link https://dev.to/adammc331/how-to-properly-design-a-database-part-1-2h6f %}

----------------------------

<a name="chapter-10"></a>
## Join

Because our database contains tables which are [normalised](https://www.essentialsql.com/get-ready-to-learn-sql-database-normalization-explained-in-simple-english/) you may not find all the data you need on one single table. To put the data back together in a way that makes the most sense for us we use JOINs.  This adds columns from multiple tables into one dataset.  

Use an INNER JOIN, shortened to 'JOIN' to find the match between two tables.  You need a column on both tables that you join ON, this is where the matching happens.  Any results where there is not a match are discarded.

![inner](https://thepracticaldev.s3.amazonaws.com/i/4awenpvfcedaz8t7ldx8.PNG)

Use a LEFT JOIN when you want to find a match between two tables, but also show a NULL where there is no match from the right table. A RIGHT JOIN does the same but in reverse.

Like the INNER JOIN, you need a column to join ON. Unlike the INNER JOIN, a NULL is used to show there is no match between the two tables.

![outer](https://thepracticaldev.s3.amazonaws.com/i/rnhge20cokfe29jol171.PNG)

Katie has written a great post on 'Every JOIN you will ever need' using the Oracle syntax.

{% link https://dev.to/katiekodes/every-sql-join-youll-ever-need-2hbd %}


----------------------------

<a name="chapter-11"></a>
## Key

A primary key is a column that best identifies one unique row, and identifies each record as unique, like an ID

- It ensures that there are no duplicates
- It cannot be unknown (NULL)
- There can only be one primary key per table

A foreign key is a column that matches a primary key in another table and enforces integrity between the two.

To create a primary key in SQL Server add the reserved words 'primary key' after the data type of your chosen column.

```sql
create table students (
  id int not null primary key,
  firstname varchar(255) not null,
  lastname varchar(255) not null,
);
```


Lenique puts this into practice with this post on relational model design.

{% link https://dev.to/leniquenoralez/dbms-for-application-development-relational-model-relational-database-3nl8 %}


----------------------------

<a name="chapter-12"></a>
## Lock

When two users try to query or update the same table at the same time it may result in a lock. In the same way that two people with ATM cards for the same bank account are trying to withdraw the same $100 from the same bank account, one will be locked out while the first transaction is completed.

Rhymes does a great job of explaining how it works on the database:

> "...database locks serve the purpose of protecting access to shared resources (tables, rows, data).

In a system where tens if not hundreds of connections operate on the same dataset, there has to be a system to avoid two connections invalidating each other's operation (or in other cases causing a deadlock) ...

Locks are a way to do that. An operation comes to the database, declares it needs a resource, finishes its modification, and then releases such resource so the next operation can do the same. If they didn't lock their resource two operations might overwrite each other's data causing disasters.

{% link https://dev.to/integerman/sql-server-locking-4beo %}

----------------------------

<a name="chapter-13"></a>
## Massive Parallel Processing

In Massively Parallel Processing databases, like Redshift, data is partitioned across multiple compute nodes with each node having memory to process data locally.

Redshift distributes the rows of a table to the nodes so that the data can be processed in parallel. By selecting an appropriate distribution key for each table, the workload can be balanced.

Read more about Redshift with alexantra who has written a complete guide to Redshift:

{% link https://dev.to/alexantra/the-r-a-g-redshift-analyst-guide-what-is-redshift-fc1 %}

----------------------------

<a name="chapter-14"></a>
## Normalisation

Database normalisation increases data integrity and allows new data to be added without changing the underlying structure.

- <strong>Eliminate or minimise duplication</strong> - repeating a value across multiple tables means that tables take up more space than needed which increases storage costs. Storing customers' address details on one table with keys linking to their orders will take up less space than repeating address details on each row of the order table.

- <strong>Simplify updates to data</strong> - by keeping a value in one table with a key to another we minimise the risk of errors when updates are made. If there are two places where a customer's email is stored and only one gets updated there will be confusion over which one is correct.

- <strong>Simplify queries</strong> - searching and sorting becomes easier if there is no duplication on tables.

Read more about normalisation:

{% link https://dev.to/gladuz/what-is-a-database-normalization-bbn %}

----------------------------

<a name="chapter-15"></a>
## OLTP v OLAP

OLTP and OLAP refer to types of databases and tools that perform different functions.

- OLTP - Online Transaction Processing - used for fast data processing and responds immediately to queries.
- OLAP - Online Analytics Processing - used for storing historical data and data mining.

Read more about OLTP:

{% link https://dev.to/vikastwittes/revolutionize-the-performance-in-sql-server-with-in-memory-oltp-system-41nn %}

----------------------------

<a name="chapter-16"></a>
## Privileges

If you intend on sharing a table with your colleagues who have access to your schema, you need to grant access to them. This keeps data locked down to just those who need to see it.

```sql
GRANT ALL ON <schemaname.tablename> TO <username>  
-- if you would like them to SELECT, UPDATE and DELETE

GRANT SELECT ON <schemaname.tablename> TO <username> 
-- if you would like them to be able to only SELECT
```

Read more about permissions and everything else you need to know about databases:

{% link https://dev.to/lmolivera/everything-you-need-to-know-about-relational-databases-3ejl %}

----------------------------

<a name="chapter-17"></a>
## Query Plan

When we run a query the SQL engine considers the joins, and the indexes, whether it will scan through the whole table or be faced with table locking.

In SQL Server we can use the [Execution Plan](https://docs.microsoft.com/en-us/sql/relational-databases/performance/display-an-actual-execution-plan?view=sql-server-ver15) to visualise runtime information and any warnings.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/22mek5y6qjzfp75qbo77.png)

<center>*From the SQL Server documentation*</center>

In PostgreSQL we can check the query plan using the EXPLAIN command:

```sql
EXPLAIN -- show the execution plan of a statement
EXPLAIN ANALYZE -- causes the query to be executed as well as explained
```

Read more about what each query looks like and how to interpret the results:

{% link https://dev.to/calebhearth/reading-a-postgres-explain-analyze-query-plan-3gb8 %}

----------------------------

<a name="chapter-18"></a>
## Recovery

Disaster Recovery in the database world relates to the backups, logs and replication instances maintained while everything is working fine. These can then be switched on, switched over, and analysed if there is a hardware failure, natural disaster, or even human error.

- <strong>Failover</strong> - multiple clusters are set up so if one fails the other can take over.

- <strong>Mirroring</strong> - maintaining two copies of the same database at different locations. One is in offline mode so we know where things are at when we need to use it.

- <strong>Replication</strong> - the secondary database is online and can be queried.  This is not only good for Disaster Recovery but can be useful if you utilise one instance for reporting and one for live queries.  If you are using AWS setting this up takes just a few clicks.

{% link https://dev.to/thamaraiselvam/the-need-for-database-replication-2ncm %}


----------------------------

<a name="chapter-19"></a>
## System Tables

In SQL Server these are often referred to as system tables and views. They can be found in the master database, which holds data about the database. 

Examples of system views
- sys.objects - shows each object, its type and created date
- sys.indexes - shows each index and type
- information_schema.columns - shows each column, its position and datatype

In PostgreSQL, a similar collection of tables can be found in the information_schema and PostgreSQL catalog.

Examples of catalog objects
- information_schema.tables - shows each object, its type and created date
- pg_index - shows each index and type
- information_schema.columns - shows each column, its position and datatype

{% link https://dev.to/yugabyte/sql-tips-tricks-counting-rows-4dgn %}

----------------------------

<a name="chapter-20"></a>
## Truncate v Drop

Both of these commands will remove the data from a table but in different ways.

- TRUNCATE is a DDL command which removes the contents of the table while leaving the structure in place

```sql
truncate table marketing.emailcampaign
```

- DELETE is a DML command which removes rows given a WHERE clause

```sql
delete from 
  marketing.emailcampaign
where
  month = 'January'
```

For a breakdown of which commands fall into DDL and which are DML commands check out this post.

{% link https://dev.to/l0l0l0l/sql-overview-and-types-of-commands-3pd7 %}

----------------------------

<a name="chapter-21"></a>
## Union

While a JOIN combines rows of columns horizontally, a UNION combines the results vertically. Using a UNION combines the result of two queries into one column and removes duplicates. If your query has multiple columns, they need to be in the same order to complete the UNION.

![union](https://thepracticaldev.s3.amazonaws.com/i/76x161yx9qx01nw5wihc.PNG)

```sql
select *
from
  orders
union
select *
from
  inventory
```

The UNION ALL combines the results of two queries the same as a UNION but keeps the duplicates in the result.

![unionall](https://thepracticaldev.s3.amazonaws.com/i/eypfji1dzlvquhhaccn0.PNG)

```sql
select *
from
  orders
union all
select *
from
  inventory
```

{% link https://dev.to/wendisha/sql-union-operator-2pmc %}


----------------------------

<a name="chapter-22"></a>
## View

Views are not tables, they are queries that are executed on the fly and are used as a way to create a level of abstraction from the base table.

Joe sums it up perfectly in his post

>A view is a stored query. When you create a database view, the database stores the SQL you gave it. Then, when you come along and query that view, the database takes the stored view query, adds in the extras from the query against the view, and executes it. That's it!

{% link https://dev.to/thatjoemoore/database-views-dont-exist-4ho7 %}

----------------------------

<a name="chapter-23"></a>
## Window Function

A window function gets its name because, unlike an aggregate function, it keeps each row intact and adds a row number or running total.

Here is an example using the orders table that returns a rank using the order_value.

```sql
select
  order_id,
  order_name
  order_date,
  rank() over(order by amount_due desc) as rank
from 
  dbo.orders
```

{% link https://dev.to/kaysauter/introduction-into-window-functions-on-sql-server-1k6o %}

----------------------------

<a name="chapter-24"></a>
## XML

We can import files into tables using the [import/export wizard](https://docs.microsoft.com/en-us/sql/relational-databases/import-export/import-flat-file-wizard?view=sql-server-ver15). But they don't have to just be csv or txt files. By using a few lines of code we can [import XML](https://docs.microsoft.com/en-us/sql/relational-databases/import-export/examples-of-bulk-import-and-export-of-xml-documents-sql-server?view=sql-server-ver15) as well.

Read more with instructions:

{%link https://dev.to/booyaa/sql-developers-new-format-hints-5c6g %}

----------------------------

<a name="chapter-25"></a>
## Year

The syntax used to calculate the difference between two dates varies between databases.  This adds complexity when moving between databases so keep this in mind on your next migration project.


{% link https://dev.to/retool/formatting-and-dealing-with-dates-in-sql-5hmh %}


----------------------------

<a name="chapter-26"></a>
## Zero

NULL means that the value is unknown, not zero and not blank.  This makes it difficult to compare values if you are comparing NULLs with NULLs. 

Because NULL is not a value we can't use comparison operators.  Instead, we need to use the IS, and IS NOT operators:

```sql 
select * 
from 
  inventory
where 
  unitprice is not null
```

By default, NULLs will appear as the largest value making sorting at best annoying and at worse misleading. To get around this we can use COALESCE to treat NULLs as a 0. 

```sql 
select 
  itemname, 
  coalesce(unitprice, 0)
from 
  inventory
order by 2
```

{% link https://dev.to/yuyabu/sqlhow-to-compare-with-null-without-is-null-operator-14d5 %}

----------------------------

There we have it, a quick introduction to the key terms, concepts and jargon for those new to SQL and databases.