FR

Writing SQL ยท Chapter 6

Working with columns

7 min read ยท 8 questions

SELECT does more than pick columns: it can also compute new ones, rename them, add constants and remove duplicates. This chapter covers these operations.

Selecting every column

The star * selects every column of the table named in the FROM:

-- The star selects every column of the product table
SELECT *
FROM product

Question 6.1

Display every column of the customer table.

Your answer

-- Question 6.1: write your query here
SELECT 
Show the solution
SELECT *
FROM customer

Column names with a space

When a column name contains a space or a special character, like VolKilo (COPA), it must be written in double quotes:

SELECT CustomerID, ProductID, "VolKilo (COPA)"
FROM perform21

Putting spaces in column names is nonetheless bad practice. They force you to add quotes everywhere, which makes queries heavier and multiplies mistakes. And each DBMS has its own syntax for them, which makes code less portable:

-- SQL Server: square brackets
SELECT [Creation Date], [Customer Name] FROM Orders;

-- PostgreSQL, Oracle, DuckDB: double quotes
SELECT "Creation Date", "Customer Name" FROM Orders;

-- MySQL: backticks
SELECT `Creation Date`, `Customer Name` FROM Orders;

Question 6.2

Display the CustomerID, ProductID, VolKilo (COPA), NOS (COPA) and COGS (COPA) columns of the perform21 table.

Your answer

-- Question 6.2: write your query here
SELECT 
Show the solution
SELECT CustomerID, ProductID, "VolKilo (COPA)", "NOS (COPA)", "COGS (COPA)"
FROM perform21

The last three columns contain a space and brackets: they go in double quotes.

Computing a new column

SELECT can display the result of a calculation on existing columns, with the operators +, -, *, /.

Imagine the scale that weighs orders is badly calibrated and takes 5 kg off every weighing. To correct it, add 5 kg to each volume:

SELECT CustomerID, ProductID, "VolKilo (COPA)" + 5
FROM perform21

The new column is named after its calculation, which is hard to read. The keyword AS gives it a name, called an alias:

SELECT CustomerID, ProductID, "VolKilo (COPA)" + 5 AS corrected_volume
FROM perform21

Question 6.3

Display CustomerID, ProductID, NOS (COPA), COGS (COPA) and a new column margin that recomputes the gross margin from revenue and cost.

Reminder: NOS (COPA) is revenue (positive) and COGS (COPA) is the purchase cost, recorded as a negative number.

Your answer

-- Question 6.3: write your query here
SELECT 
Show the solution
SELECT CustomerID, ProductID, "NOS (COPA)", "COGS (COPA)",
       "NOS (COPA)" + "COGS (COPA)" AS margin
FROM perform21

Since the cost is already negative, you add it to revenue: 127,652 + (โˆ’51,445) = 76,207. Writing "NOS (COPA)" - "COGS (COPA)" would add the cost instead of subtracting it. The result matches the GP (COPA) column, which lets you check your calculation. Always look at a column's sign before computing with it.

Question 6.4

Display CustomerID, ProductID, Date and the margin rate of each row of perform21, as a percentage rounded to one decimal place, in a column named margin_rate. The margin rate is the gross margin divided by revenue. To round, use ROUND(value, 1).

Your answer

-- Question 6.4: write your query here
SELECT 
Show the solution
SELECT CustomerID, ProductID, Date,
       ROUND("GP (COPA)" / "NOS (COPA)" * 100, 1) AS margin_rate
FROM perform21

Divide the margin by revenue, multiply by 100 to get a percentage, then round.

Watch out for division by zero: perform21 has no rows at 0, but later years do. Depending on the DBMS, dividing by zero raises an error (PostgreSQL, SQL Server) or returns infinity and NaN (DuckDB). Chapter 13 shows how to guard against it with NULLIF.

Adding a constant

A column can hold the same value on every row. Just write the value in the SELECT: in single quotes for text, without quotes for a number.

SELECT *, 'FR' AS country_code
FROM customer

This trick is useful to label data before stacking it with other data (we will see this in the chapter on UNION).

Question 6.5

Display CustomerID and CustomerName from the customer table, plus a type column equal to 'customer' on every row.

Your answer

-- Question 6.5: write your query here
SELECT 
Show the solution
SELECT CustomerID, CustomerName, 'customer' AS type
FROM customer

Concatenating text

The || operator joins pieces of text end to end. Use it to build a label or a key:

SELECT CustomerName || ' (' || Channel || ')' AS label
FROM customer

Question 6.6

A row of perform21 stands for one customer, one product and one month. Build a row identifier named row_id by joining CustomerID, ProductID and Date, separated by dashes (for example 1-1-2021-08-01). Display this identifier and the NOS (COPA) column.

Your answer

-- Question 6.6: write your query here
SELECT 
Show the solution
SELECT CustomerID || '-' || ProductID || '-' || Date AS row_id,
       "NOS (COPA)"
FROM perform21

DuckDB automatically converts numbers and dates to text to concatenate them. This kind of identifier, built from the columns that make a row unique, is called a composite key: we will come back to it in the chapter on data quality.

Removing duplicates with DISTINCT

DISTINCT, placed right after SELECT, removes duplicate rows from the result.

-- One row per sale: 21,736 rows
SELECT ProductID
FROM perform21
-- One row per distinct product: 520 rows
SELECT DISTINCT ProductID
FROM perform21

With several columns, DISTINCT compares whole rows: it keeps each distinct combination.

-- The distinct customer-product pairs: 2,845 rows
SELECT DISTINCT CustomerID, ProductID
FROM perform21

Question 6.7

Display the list of distinct months in perform21 (the Date column).

Your answer

-- Question 6.7: write your query here
SELECT 
Show the solution
SELECT DISTINCT Date
FROM perform21

There are 12, from January to December 2021: each month is represented by its first day.

Question 6.8

Display the list of distinct categories and sub-categories in the product table (each combination once).

Your answer

-- Question 6.8: write your query here
SELECT 
Show the solution
SELECT DISTINCT Category, SubCategory
FROM product

DISTINCT applies to the combination of both columns: the Capsules category appears several times, once per sub-category.