Jed Rembold
Monday, October 27, 2025
Given the starting table called rev, what
is the output of the query?
| name | num |
|---|---|
| A | 1 |
| B | 2 |
| C | 3 |
| D | 4 |
| E | 5 |
SELECT name
FROM rev
WHERE num IN (
SELECT
num - (SELECT avg(num) FROM rev)
FROM rev
WHERE num >= ALL (
SELECT num FROM rev
)
);
Sometimes you may want to use the same derived tables multiple places in a query
You could copy and paste those subqueries, but there is a better way
Common Table Expressions or CTEs are a way for you to define up front a derived table that can be referenced anywhere in the rest of the query
To do so, you use a WITH keyword at
the start of the query:
WITH
|||derived table name||| (|||column names|||) AS (
|||subquery|||
)
SELECT ...Using a CTE and other subqueries, let’s extract the middle 50% of the taxi_rides by duration.
| Name | Color | Condition | Number |
|---|---|---|---|
| Apple | Red | Good | 5 |
| Orange | Orange | Bad | 3 |
| Cherry | Red | Good | 10 |
| Banana | Yellow | Good | 1 |
| Pineapple | Yellow | Bad | 4 |
| Color | Good | Bad |
|---|---|---|
| Red | 15 | 0 |
| Orange | 0 | 3 |
| Yellow | 1 | 4 |
Standard SQL has no way to create these cross-tabulations
Postgres has a function to help, but it is located in an extension or module
To use an extension, you need only enable it for your particular database
CREATE EXTENSION |||extension name|||;To facilitate making pivot tables, we need to add the
tablefunc extension to our database, which
will add the crosstab function
You can always remove an extension using
DROP if you need later
crosstab function has a lot going on,
so let’s break things downSELECT *
FROM crosstab(
|||subquery 1 string|||,
|||subquery 2 string|||
)
AS (
|||row label column||| TEXT,
|||column 1||| |||type 1|||,
|||column 2||| |||type 2|||,
⋮
);
crosstab as strings\$$ to indicate the start and end of the
string
Let’s construct a pivot table comparing the total number of taxi rides at different days of the week across different hours.
CASE statement to
accomplish this
CASE
WHEN |||some condition||| THEN |||output|||
WHEN |||some other condition||| THEN |||diff output|||
⋮
ELSE |||more diff output|||
END
Comparisons are made in order, so the first condition that matches, that output is used
If you do not include an ELSE part,
then NULL will be output if nothing else
matches
CASE statements most often show up in
SELECT statements where column outputs are
being selected, but they could potentially also show up in filtering or
ordering statements
A CASE statement will not evaluate
results where the condition is not met, so they can be used to prevent
certain errors as well (such as dividing by 0)
SELECT
CASE WHEN |||col||| != 0 THEN 5/|||col||| END
FROM |||table|||;Let’s compute how many taxi rides were considered:
CASE, SQL also has the
COALESCE statementCOALESCE technically returns the first
non-null value in the comma separate list of valuesNULL valuesSELECT
student_id,
COALESCE(grade, 0)
FROM grades;
Using the same grade book tables from last class (here if you need them again), do the following:
||
operator. So fname || ' ' || lname would give
the first and last name with a space between as a single string. Feel
free to use joins here.