Filtering & predicates
Concept  ·  SQL & Querying

BETWEEN '2024-01-01' AND '2024-01-31' loses Jan 31's daytime; half-open >= / < is the bar.

BETWEEN a AND b is inclusive on both ends, and a bare date is midnight. So BETWEEN a date AND a month-end date stops at that day's midnight and loses everything later that day. The half-open form >= start AND < next-start keeps the whole span.

See it break
swipes
idts
12024-01-31 09:00
22024-02-01 00:00
32024-01-15 12:00
The trap
SELECT
  id
FROM
  swipes
WHERE
  ts BETWEEN TIMESTAMP '2024-01-01'
  AND TIMESTAMP '2024-01-31'
ORDER BY
  id;
The fix
SELECT
  id
FROM
  swipes
WHERE
  ts >= TIMESTAMP '2024-01-01'
  AND ts < TIMESTAMP '2024-02-01'
ORDER BY
  id;
The trap
3
The fix
1
3

The January report drops every swipe after midnight on the 31st — BETWEEN's closed upper bound is really '2024-01-31 00:00'.

The rule

Filter timestamp ranges with >= start AND < next_start — the half-open interval that includes the last day's daytime.

Shows up elsewhere
Half-open intervals
Try one →Prove it in practice →