Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Find Set Intersections & Unions

Learn how to use Redis commands to find intersections and unions of sets, with hands-on exercises and troubleshooting tips.

Focus: find set intersections and unions

Sponsored

Have you ever needed to compare two sets of data — like finding which users are in both a beta group and a VIP list, or combining the tags from multiple articles? Manually looping through lists in Python or writing complex SQL is slow and error-prone. Redis Sets come to the rescue with built-in commands like SINTER, SUNION, and SDIFF that perform these operations instantly in-memory, giving you results in milliseconds.

The Problem This Lesson Solves

When working with collections of unique elements, you often need to find common members, merge sets, or identify differences. Without a dedicated tool, you'd write nested loops or use hash-based lookups that are fragile and slow as data grows. Redis Sets are designed exactly for this: they store unique strings and offer atomic set operations that run at server-side speed, saving you from moving data back and forth.

Core Concept / Mental Model

Think of Redis Sets as mathematical sets — unordered collections of unique items. The four key operations mirror their math counterparts:

  • Union (SUNION) – all items from Set A and Set B, with duplicates removed.
  • Intersection (SINTER) – items that appear in both Set A and Set B.
  • Difference (SDIFF) – items in Set A but not in Set B.
  • Difference (SDIFFSTORE, SINTERSTORE, SUNIONSTORE) – store the result into a new Set for later use.

💡 Pro tip: All these operations are O(N) where N is the combined size of the input sets. For large sets (millions), the server still delivers sub‑millisecond responses — but avoid storing the result into a key you immediately delete.

The Commands at a Glance

Command Purpose Returns
SINTER key [key ...] Intersection of two or more Sets Set of members present in all
SUNION key [key ...] Union of two or more Sets Set of all distinct members
SDIFF key [key ...] Difference of first Set minus the rest Members in first but not others
SINTERSTORE dest key [key ...] Intersection stored in dest Integer (size of result)
SUNIONSTORE dest key [key ...] Union stored in dest Integer (size of result)
SDIFFSTORE dest key [key ...] Difference stored in dest Integer (size of result)

How It Works Step by Step

  1. Add members to one or more Sets using SADD.
  2. Call the desired operationSINTER, SUNION, or SDIFF — passing the Set keys in order.
  3. Examine the result – it's a Set, so you can use SMEMBERS to view it (or use the result inline).
  4. Optionally persist the result with *STORE variants to avoid recomputing expensive operations.

RDBMS Analogy

In SQL, intersection is INNER JOIN on unique IDs. Union is UNION DISTINCT. Redis performs these joins server-side without transferring data — much faster for real‑time scenarios like analytics dashboards.

Hands-On Walkthrough

Let's build a real scenario: you have two customer segments — beta_users and vip_users. You need to find overlapping users, merge them, and identify non‑VIP beta testers.

Example 1: Basic Intersection and Union

import redis

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

# Create sets
r.delete('beta_users', 'vip_users')
r.sadd('beta_users', 'alice', 'bob', 'charlie', 'diana')
r.sadd('vip_users', 'bob', 'diana', 'eve', 'frank')

# Intersection — users in both groups
common = r.sinter('beta_users', 'vip_users')
print("Beta & VIP intersection:", sorted(common))
# Output: Beta & VIP intersection: ['bob', 'diana']

# Union — all users combined
all_users = r.sunion('beta_users', 'vip_users')
print("All users (union):", sorted(all_users))
# Output: All users (union): ['alice', 'bob', 'charlie', 'diana', 'eve', 'frank']

Example 2: Difference and Store

# Beta users NOT in VIP
beta_only = r.sdiff('beta_users', 'vip_users')
print("Beta only:", sorted(beta_only))
# Output: Beta only: ['alice', 'charlie']

# Store union for later analytics
r.sunionstore('all_customers', 'beta_users', 'vip_users')
print("Stored union size:", r.scard('all_customers'))
# Output: Stored union size: 6

# Clean up
r.delete('beta_users', 'vip_users', 'all_customers')

Example 3: Command Line with redis-cli

# Add tags to articles
redis-cli SADD article:1:tags redis set intersection
redis-cli SADD article:2:tags redis set union database

# Find common tags
redis-cli SINTER article:1:tags article:2:tags
# 1) "redis"
# 2) "set"

# All unique tags across both articles
redis-cli SUNION article:1:tags article:2:tags
# 1) "redis"
# 2) "set"
# 3) "intersection"
# 4) "union"
# 5) "database"

Example 4: Using Multiple Sets

# Three user roles: admin, moderator, editor
r.sadd('admin', 'alice', 'bob')
r.sadd('moderator', 'bob', 'charlie')
r.sadd('editor', 'diana', 'bob')

# Users with at least two roles
# Any user appearing in at least two sets = union of all pairs? 
# Simpler: intersection of all three?
all_three = r.sinter('admin', 'moderator', 'editor')
print("In all three roles:", list(all_three))
# Output: In all three roles: ['bob']

# Users with only admin role (exclusive)
exclusive_admin = r.sdiff('admin', 'moderator', 'editor')
print("Exclusive admin:", list(exclusive_admin))
# Output: Exclusive admin: ['alice']

Compare Options / When to Choose What

Operation When to Use Performance
SINTER Find common members (e.g., mutual followers) O(N*M) worst-case
SUNION Merge data from multiple sources O(N) with N total elements
SDIFF Identify unique items in one set only O(N) of first set
*STORE commands Cache expensive results for reuse Slower upfront, faster later

⚠️ Be careful with SDIFF on large first sets — if the first set has 10 million items and the second has 1 million, the operation is still O(10M). For repeated differences, store the result with SDIFFSTORE.

Redis vs. Alternatives

  • Redis Sets – best for real-time, moderate-sized (< 1B total elements) operations on unique values.
  • Sorted Sets (ZSET) – if you need ordered results or ranking, use ZINTERSTORE/ZUNIONSTORE (covered in later lessons).
  • Python native sets – fine for small data (<10k items) in a single process, but slower for cross-network data sharing.

Troubleshooting & Edge Cases

Mistake 1: Forgetting sets are unordered

result = r.sinter('set_a', 'set_b')
print(result[0])  # Can't rely on order!

Fix: Use SMEMBERS or sort in your application (sorted(result)).

Mistake 2: Passing non-existent keys

r.sinter('missing_set', 'another_set')
# Redis treats missing key as empty set, so result is empty — silent failure.

Fix: Check existence with EXISTS before operations if results surprise you.

Mistake 3: Running SDIFF expecting symmetric difference

SDIFF A B gives A - B. For symmetric difference (items in either but not both), you need (A - B) ∪ (B - A).

Common Errors

  • WRONGTYPE Operation against a key holding the wrong kind of value – the key is not a Set. Check with TYPE key.
  • Memory blow-up on large unions – if you SUNION three sets of 10M each, Redis holds 30M elements temporarily. Use SUNIONSTORE to write directly to a new key and avoid client‑side memory thrashing.
  • Network latency – each command is a round trip. Batch operations with pipeline() for better throughput.

What You Learned & What's Next

You now understand how to find set intersections and unions using Redis's SINTER, SUNION, and SDIFF commands, and how to persist results with *STORE variants. These operations are foundational for building real‑time recommendation engines, audience overlap reports, and access control systems.

In the next lesson, you'll explore Sorted Sets — ordered collections that let you rank leaderboards and handle weighted intersections. You'll learn ZADD, ZRANGE, and weighted union/intersection commands that power gaming and analytics use cases.

Practice recap

Try this exercise on your own: create three sets — students_python, students_js, and students_devops. Add at least 5 members each, with some overlap. Then find: (a) students in all three courses (intersection), (b) students in any of the three (union), (c) students in Python but not in JS (difference). Use SINTERSTORE to save the intersection for reporting.

Common mistakes

  • Assuming sets are ordered — always sort results client-side with sorted().
  • Forgetting that a non-existent key is treated as an empty set, which can silently return empty results.
  • Using SDIFF expecting symmetric difference, but only getting members from the first set.
  • Running large unions or intersections without storing the result, causing memory spikes client-side.

Variations

  1. Use SINTERSTORE, SUNIONSTORE, or SDIFFSTORE to persist the result for later reuse instead of recomputing.
  2. For ordered results, consider ZINTERSTORE or ZUNIONSTORE with sorted sets and weights.
  3. Combine SINTER with SADD in a Lua script to atomically compute and store intersections without client round-trips.

Real-world use cases

  • Identify mutual followers or common friend groups between two users in a social network.
  • Merge tags from multiple blog posts or articles to generate a unified topic cloud.
  • Find users who belong to a beta program but are not yet in the VIP segment for targeted promotions.

Key takeaways

  • Redis provides SINTER, SUNION, and SDIFF for instant set math at server speed.
  • Use *STORE commands to cache expensive set operations and avoid recomputing.
  • Non-existent keys are treated as empty sets — always check with EXISTS for unexpected empty results.
  • Sets are unordered; sort results client-side for consistent output.
  • For real-time analytics dashboards, Redis set operations outperform SQL JOINs and client-side loops.
  • Large union/intersection results should be stored server-side to reduce network and memory pressure.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.