30-Day Page View Counts

An easy SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
easy
Seniority
L3
Asked in
Meta

Problem

Give us each user's total page views in page_views for 2025 up to and including December 28, counting every view, repeat hits on the same page included. We close the snapshot on that final day, so a visit at any hour of December 28 belongs in it.

Thirty days of engagement. Quick snapshot.

Tables

page_views

Columns: view_id INTEGER, page_url TEXT, user_id INTEGER, referrer TEXT, dur_ms INTEGER, device TEXT, viewed_at TEXT

page_views: 10 of 200 rows
view_idpage_urluser_idreferrerdur_msdeviceviewed_at
5053/products1555amazon.com637desktop2026-09-02 01:09:00
5106/checkout1652twitter.com774tablet2026-09-03 02:18:00
5159/profile1749github.com911Mobile2026-09-04 03:27:00
5212/search1846NULL1048DESKTOP2026-09-05 04:36:00
5265/about1943reddit.com1185mobile2026-09-06 05:45:00
5318/blog/intro1555NULLNULLdesktop2026-09-07 06:54:00
5371/pricing1652bing.com1459tablet2026-09-08 07:03:00
5424/docs/api1749news.ycombinator.com1596Mobile2026-09-09 08:12:00
5477/settings1846NULL1733DESKTOP2026-09-10 09:21:00
5530/Home1943bing.com1870mobile2026-09-11 10:30:00

Expected output

First 4 of 4 rows
user_idtotal_views
NULL2
8762
13613
184613

Worked solution and explanation

What this really is

This is a boundary question dressed up as an engagement report. The count per user is the easy part; anyone writes GROUP BY user_id and COUNT(*). What separates candidates is the edge of the window: viewed_at is a timestamp, not a date, and the snapshot is closed on a calendar day. Write viewed_at BETWEEN '2025-01-01' AND '2025-12-28' and the upper bound quietly becomes midnight, so every view after 00:00:00 on December 28 falls out. The one day the report is built around becomes the one day it gets wrong.

Range on the raw timestamp
viewed_at BETWEEN '2025-01-01' AND '2025-12-28' reads as inclusive but stops at 2025-12-28 00:00:00. A view at 09:15 on the 28th is excluded and every user active that day comes up short.
Range on the calendar day
DATE(viewed_at) BETWEEN '2025-01-01' AND '2025-12-28' compares days to days. Any hour of December 28 maps to the date December 28 and is counted.

Step 1: Pin both ends to whole days

The snapshot opens on January 1 and closes at the end of December 28. Say both bounds as days before you write a literal; the start is harmless at midnight, the end is not.

Step 2: Compare on DATE(viewed_at)

Truncating the timestamp to its day makes both bounds of BETWEEN mean whole days, which is exactly what "up to and including December 28" means to the business asking.

Step 3: Count every row per user_id

COUNT(*) counts each view. A repeat hit on the same page is still a view, so COUNT(DISTINCT page_url) answers a different question and understates the heavy users. Grouping on user_id also keeps the anonymous rows together as their own line.

Per-user views through the inclusive final day
SELECT user_id, COUNT(*) AS total_views
FROM page_views
WHERE DATE(viewed_at) BETWEEN '2025-01-01' AND '2025-12-28'
GROUP BY user_id

Common follow-up questions