Jed Rembold
Wednesday, September 3, 2025
Suppose a table had been created using the SQL statement below. How would you then query for the most recently measured number of positive cases from schools beginning with “University”?
CREATE TABLE cases (
id INT,
school_name VARCHAR(50),
case_positive INT,
tests_run INT,
date_taken DATE
);
SELECT case_positive FROM cases
WHERE school_name LIKE 'University_'
ORDER BY date_taken;
SELECT case_positive FROM cases
WHERE school_name LIKE 'University%'
ORDER BY date_taken DESC;
SELECT case_positive FROM cases
WHERE school_name LIKE '%University%'
ORDER BY case_positive DESC,
date_taken DESC;
SELECT case_positive FROM cases
WHERE school_name LIKE '%University%'
ORDER BY date_taken DESC;
NULL entryCHAR(n): A fixed length column of
n characters. Always uses this amount of
characters, padding with spaces if your stored sequence of characters is
shorter.
(n) is the same as
CHAR(1)VARCHAR(n): A variable length column with
a maximum of n characters. If your stored
sequence is smaller, then no padding is done and the data is stored as
is.
(n) is the same as
TEXTTEXT★: A
variable length column of “unlimited length” (about 1 GB).★ – Postgres specific, though similar implementations exist in other variants
CHAR unless what
you are storing is always a given length of characters
VARCHAR or
TEXT in most situations
VARCHAR is more portable, but make sure
to choose a max that is well above whatever your longest sequence of
characters could beVARCHAR if you
want an error to be output if too many characters are
enteredTEXT should always work| Type | Size | Range |
|---|---|---|
SMALLINT |
2 bytes | ±32,767 |
INTEGER |
4 bytes | ±2,147,483,648 |
BIGINT |
8 bytes | ±9,223,372,036,854,775,808 |
SMALLINT is generally only used if disk
space is at a premiumBIGINT if sure that
INTEGER is insufficientSMALLSERIALSERIALBIGSERIALINSERT is interrupted because of an
error, that unique integer is basically skippedThe SERIAL datatypes are Postgres
specific
Since Postgres 10 the SQL core version with
IDENTITY has been supported
Automatically fill the column with the incremented number:
INTEGER GENERATED ALWAYS AS IDENTITYAutomatically fill column but allow overwriting:
INTEGER GENERATED BY DEFAULT AS IDENTITYNUMERIC(|||precision|||, |||scale|||)DECIMAL(|||precision|||, |||scale|||)NUMERIC(5,2) = 192.84NUMERIC(10,2) = 192.84NUMERIC(15,10) = 192.8374650000NUMERIC(6,3) = 192.837NUMERIC(4,2) =
ERRORNUMERIC(5) = 193
NUMERIC = 192.837465
REALDOUBLE PRECISIONREAL will show at most 9 significant
digits and takes up 4 bytesDOUBLE PRECISION will show at most 17
significant digits and takes up 8 bytes
FLOAT
to be synonymous with DOUBLE PRECISION
A table is made as shown to the right. Only one of the rows
below could be added to that table using
INSERT INTO without causing an error. Which
row could be successfully added?
CREATE TABLE revq (
col1 CHAR(2),
col2 TEXT,
col3 SMALLINT,
col4 NUMERIC(3,2),
col5 REAL
);
| Answer | col1 | col2 | col3 | col4 | col5 |
|---|---|---|---|---|---|
| A | ‘OR’ | ‘Hello!’ | 30200 | 12.2 | 3.14 |
| B | ‘12’ | ‘How odd!’ | 43210 | 2.23 | 2.718281828 |
| C | ‘C’ | ‘Puzzling.’ | 13.6 | 1.1 | 1.41 |
| D | ‘okay’ | ‘Mysterious…’ | 2132 | 8 | 1.618 |
| Name | Storage Size | Lowest | Highest | Resolution |
|---|---|---|---|---|
DATE |
4 bytes | 4713 BC | 5874897 AD | 1 day |
TIME |
8 bytes | 00:00:00 | 24:00:00 | 1 μs |
TIMESTAMP |
8 bytes | 4713 BC | 294276 AD | 1 μs |
INTERVAL |
16 bytes | -178000000 yrs | -178000000 yrs | 1 μs |
| January 18, 2022 | 1/18/2022 | 01/18/22 |
| 2022-Jan-18 | 18-Jan-2022 | Jan-18-22 |
| 20220118 | Jan 18, 22 |
TIME is technically without timezoneTIME WITH TIME ZONE is, as expected,
including a timezone
TIMETZ★| 16:05:06 | 16:05 | 04:05 PM |
| 4:05:06.123 PM 0 | 4:05:06 AM |
TIMESTAMP field holds basically both a
date and a time (in that order)TIMESTAMP by itself is without a
timezone, as per SQL standardsTIMESTAMP WITH TIME ZONE is with a
timezone. Shorthand in Postgres is
TIMESTAMPTZ★There are plenty of instances where you may need to convert between types
Can use the CAST function to convert
between data types (where it makes sense)
Core syntax is
CAST(col_name AS new_data_type)Postgres has a shorthand conversion syntax that uses double colons:
col_name::new_data_type