Field note · March 17, 2025
What rated_at actually contains in movie-ratings
9,000 rows, 8,999 distinct values, and the one fact about rated_at that changes how you query it.
Working through movie-ratings again. rated_at is the column people trip over, so here is what it actually looks like.
9,000 rows, no nulls, 8,999 distinct values. When the rating was submitted.
It runs from 2023-01-01 00:22:37 to 2025-06-19 23:13:27, covering 901 distinct days.
It is a timestamp, not a date, which means every comparison against a bare date is a comparison against midnight. rated_at <= date '2023-06-30' silently excludes almost all of 30 June. Half-open ranges — >= start and < end — avoid the whole class of off-by-one-day bugs and read no worse.
select
count(*) as rows,
count(rated_at) as present,
count(*) - count(rated_at) as nulls,
count(distinct rated_at) as distinct_values
from movie_ratings;Check the range before filtering on it. Half the "the dashboard is empty" reports we have seen are a date filter outside the data's actual range, and the query is not wrong so nothing errors.
Where this bites: 901 populated days is what any window function over this column has to work with. A seven-day lag counts rows, not days — so if a day is missing, lag(7) quietly compares against eight days ago and the week-over-week number is wrong in a way that looks plausible.
The grain is one row per user-film rating, which is the context every one of those numbers depends on. None of them survive a change of grain, which is why "profile the column" and "profile the table" are the same job. Full schema, and the CSV, on the dataset page.