Learn SQL/Intermediate/Set Operations/SQL UNION vs UNION ALL

SQL UNION vs UNION ALL

Run the same two session-cohort queries with UNION and UNION ALL, then watch user 101 appear once or twice.

What & Why

The choice between UNION and UNION ALL comes down to one question: does the combined result need every source row preserved exactly, or is a deduplicated set of distinct values what's actually wanted? Toggle between the two below — the source queries and the Venn diagram look identical either way; only the result set changes.

See How It Works

BUSINESS QUESTION

Growth wants to compare the distinct-user count with the complete membership count across the same two session cohorts.

iduser_idstarted_atended_atpage_viewsdevice
50011012024-01-16 14:20:00+002024-01-16 14:52:00+008desktop
50021022024-02-10 11:10:00+002024-02-10 11:18:00+003mobile
50031032024-03-13 08:10:00+002024-03-13 09:04:00+0012desktop
50041042024-04-03 12:00:00+00NULL1tablet
50051052024-04-04 09:00:00+002024-04-04 09:21:00+007mobile
50061062024-04-05 10:15:00+002024-04-05 10:42:00+005tablet
50071072024-04-06 13:05:00+002024-04-06 13:38:00+0010desktop
Watch compatible tables produce a set resultStep 1 of 2
Desktop session users
user_id
101
103
107
UNION
Sessions with 5–8 page views
user_id
101
105
106
Result set · 1 rows
set_operatorrow_count
UNION5

The first summary row counts five distinct users after UNION removes the second 101.

EXAMPLE QUERY
WITH desktop_users AS (
  SELECT DISTINCT user_id
  FROM growth.sessions
  WHERE device = 'desktop'
),
engaged_users AS (
  SELECT DISTINCT user_id
  FROM growth.sessions
  WHERE page_views BETWEEN 5 AND 8
),
union_rows AS (
  SELECT user_id FROM desktop_users
  UNION
  SELECT user_id FROM engaged_users
),
union_all_rows AS (
  SELECT user_id FROM desktop_users
  UNION ALL
  SELECT user_id FROM engaged_users
)
SELECT 'UNION' AS set_operator, COUNT(*) AS row_count FROM union_rows
UNION ALL
SELECT 'UNION ALL' AS set_operator, COUNT(*) AS row_count FROM union_all_rows
ORDER BY row_count;
Now You Try

Practice this concept

Growth wants to compare the distinct-user count with the complete membership count across the same two session cohorts.

Available schema
growth

Prefix tables with growth.table_name.

set_operatorrow_count
growth.sessions
ColumnType
idbigint
user_idinteger
started_attimestamp with time zone
ended_attimestamp with time zone
page_viewsinteger
devicetext
internal_session_scoreinteger
query.sql
Intermediate business practice

Sign up free to try it on a real business scenario