← All NukteSELECT * FROM TheShiraverse
Module 1 › DISTINCT & Filtering

DISTINCT & Filtering: WHERE, AND/OR, LIKE, IN & NULL

Module 1, Session 7. SELECT and WHERE, DISTINCT, IS NULL, AND/OR/NOT and brackets, LIKE/ILIKE wildcards, BETWEEN and IN. Sorting and pagination are the next session.

Jo class mein bola, yahan nukte mein likha hai.
What I said in class, written here as key points.

DISTINCT & Filtering

Ask RetailMart precise questions: keep only the rows you need with WHERE, remove repeats with DISTINCT, find missing values with IS NULL, and combine conditions with AND, OR, NOT, LIKE, BETWEEN and IN.

31
Interactive Scenes
2
Practice Arenas
8
Hands-on Drills
6
Interview Scenarios

Today’s Agenda — DISTINCT & Filtering

Four pillars: ask RetailMart for exactly the rows you need

Pillar 01
🔍 Pick the Rows
01 The Library Story: 10 Lakh Books
02 WHERE — the Row Sieve
03 DISTINCT — Remove Repeats
Pillar 02
❓ Missing Values
04 IS NULL vs the = NULL Trap
05 Practice Arena 01
06 SELECT * vs Named Columns
Pillar 03
🔗 Combine Conditions
07 AND, OR, NOT & Brackets
08 LIKE & ILIKE Patterns
09 BETWEEN & IN
Pillar 04
🎯 Practice & Next
10 Practice Arena 02
11 Interview Questions & Self-Check
12 Next class: Sorting & Pagination
💡
Why this matters: RetailMart holds 23,91,602 rows. Nobody reads them all. Every report, dashboard and interview question starts with the same skill: asking for exactly the rows you need.

Where We Left Off

From storing data correctly to asking it questions

🔑 SESSION 06 • COMPLETED

What Keys Solved

-- Session 6: one identity per row, real links
CREATE TABLE orders (
order_id    INT PRIMARY KEY,
customer_id INT REFERENCES customers(customer_id)
);
Last class, every table got keys. Roll number 1047 cannot appear twice, and an order cannot point at customer 999. The data is now clean and connected.
✓ PRIMARY KEY + FOREIGN KEY: clean, linked tables
🔍 SESSION 07 • THE MISSION

Clean Data Is Not an Answer Yet

-- The manager asks one question. We run:
SELECT * FROM sales.orders;
⚠️ 1,50,000 rows come back. Which ones did she need?
“Which orders are still not delivered? Which Gold customers use Gmail?” Scrolling through 1,50,000 rows is not an answer. Today we ask for exactly the rows we need.
🔍 Today: WHERE, DISTINCT, IS NULL, AND/OR, LIKE, IN
⚖️
The Core Distinction: Sessions 4 to 6 built tables that store data correctly. From today we ask that data questions: which rows, without repeats, without missing the empty ones.
📚
The Library With 10 Lakh Books A QUESTION WITH NO CATALOGUE
CITY CENTRAL LIBRARY EXAMPLE STORY • NAMES & NUMBERS MADE UP 🕘 CLOSING IN 1 HOUR
STEP 01 • THE REQUEST
reader-at-the-counter 6:00 PM
“I need a history book about Bharat, written after 2010, in Hindi or English. The library closes at seven.”
The library has 10 lakh books on hundreds of shelves. The old librarian has no catalogue, only her memory and her feet.
STEP 02 • WHAT GOES WRONG
📚 Every Shelf, One by One
No WHERE
With no catalogue she reads every book from the first shelf. At closing time she has checked 30,000 of 10 lakh.
🔁 Three Copies, Three “Results”
No DISTINCT
She brings back three copies of the same edition and counts them as three different books.
🔀 One “Or” in the Wrong Place
No Brackets
“History and Hindi or English”: she brings every English book in the building.
STEP 03 • THE CATALOGUE
FILTERS
🐙 One Question, Four Wishes
SELECT DISTINCT title, year
FROM library.books
WHERE genre = 'History'
  AND year > 2010
  AND language IN ('Hindi', 'English')
  AND title ILIKE '%bharat%';
-- 10 lakh cards in, 14 titles out
✓ 1 Question, 4 Conditions 14 Books in a Minute
STEP 04 • CORE PRINCIPLE
The Moral: A database without filters is a library without a catalogue. WHERE picks the rows, DISTINCT removes the repeats, AND/IN/ILIKE combine your wishes, and brackets stop one “or” from emptying the building.

Translating the Library to PostgreSQL

Every Wish Has a Clause
ROSETTA STONE • 6 CLAUSES

Each thing the reader asked for maps to one piece of a SELECT statement:

The Reader’s Wish SQL Clause What PostgreSQL Does
📚 History books only WHERE genre = 'History' PostgreSQL checks every row and keeps only those where the condition is TRUE.
📅 Written after 2010 AND year > 2010 With AND, both conditions must be TRUE for a row to stay.
🗣️ Hindi or English IN ('Hindi', 'English') One list instead of a chain of ORs, so there is no bracket to forget.
🔤 “Bharat” somewhere in the title ILIKE '%bharat%' % means any characters; ILIKE ignores capital letters, LIKE does not.
📗 Three copies of one edition DISTINCT Rows that repeat in every selected column are shown only once.
❓ Books with no year written down IS NULL year = NULL finds nothing; year IS NULL finds the blanks.
⚠️
The One Trap to Remember: AND runs before OR. “History AND Hindi OR English” means (History AND Hindi) OR English: every English book in the building. Mixing AND with OR? Put brackets.

WHERE: The Row Sieve & Predicate Evaluator

How PostgreSQL filters lakhs of tuples on the fly before delivering rows to memory.

⚙️ SIMULATE PREDICATE:
CURRENT FILTER: ALL ROWS (NO FILTER APPLIED)
CUST #101 • Ananya
tier: 'Gold' • spend: ₹45,000
status: 'Active'
● QUEUED
CUST #102 • Rohan
tier: 'Silver' • spend: ₹1,200
status: 'Active'
● QUEUED
CUST #103 • Priya
tier: 'Gold' • spend: ₹88,000
status: NULL (Unknown)
● QUEUED
CUST #104 • Kabir
tier: 'Bronze' • spend: ₹850
status: 'Inactive'
● QUEUED
Ready • Click a filter condition button to evaluate rows through PostgreSQL predicate logic. 4 / 4 ROWS PASSING

Definition: SELECT & WHERE

Pick the columns you need, then keep only the rows that match

🔄 1. SELECT — Which Columns

Name the columns you want after SELECT. Fewer columns means less data to read and send.

🛡️ 2. WHERE — Which Rows

PostgreSQL tests the condition on every row. Only rows where it is TRUE stay; FALSE and UNKNOWN are dropped.

⚖️ 3. Comparison Operators

=, <>, >, <, >=, <= work on numbers, text and dates.

SELECT and WHERE on RetailMart
PostgreSQL
STEP 1SELECT: which columns ▶ Run
SELECT first_name, last_name, tier
FROM customers.customers
LIMIT 10;
→ 3 of the 8 columns, first 10 rows
STEP 2WHERE: which rows ▶ Run
SELECT first_name, last_name, tier
FROM customers.customers
WHERE tier = 'Gold'
LIMIT 10;
→ 7,668 of 50,000 customers are Gold
STEP 3Compare with >= ▶ Run
SELECT order_id, net_total
FROM sales.orders
WHERE net_total >= 5000
LIMIT 10;
→ 1,33,097 of 1,50,000 orders are ₹5,000+

DISTINCT: The Row Deduplication Engine

How PostgreSQL collapses identical records using hash aggregation or sort-unique steps.

⚙️ EXECUTE PROJECTION:
RAW INPUT STREAM • 8 SAMPLE ROWS FROM stores.stores
Prayagraj
Noida
Kanpur
Prayagraj
Indore
Noida
Agra
Prayagraj
Standby • Click a projection button to see how DISTINCT filters identical tuple entries. 8 ROWS RECEIVED

Definition: DISTINCT & Column Aliases

Show each value once, and give columns readable names

✨ 1. DISTINCT Checks the Whole Row

SELECT DISTINCT city, state drops a row only when every selected column repeats, not just the first one.

🏷️ 2. AS Renames a Column

tier AS customer_tier changes only the heading in the result. The table itself stays the same.

⚠️ 3. Not a Free Fix

DISTINCT has to compare rows, which costs time on big tables. Never use it to hide repeats a wrong query made.

DISTINCT on RetailMart
PostgreSQL
STEP 1Each value once ▶ Run
SELECT DISTINCT city
FROM customers.addresses
LIMIT 10;
→ 70 cities in 50,000 addresses
STEP 2Checks every column ▶ Run
SELECT DISTINCT city, state
FROM customers.addresses
LIMIT 10;
→ still 70 pairs: each city is in one state
STEP 3AS: a readable heading ▶ Run
SELECT DISTINCT tier AS customer_tier
FROM customers.customers
LIMIT 10;
→ 4 tiers: Bronze, Gold, Platinum, Silver

NULL Handling: Three-Valued Logic Evaluator

Why comparing with = NULL always fails and how IS NULL solves the missing data problem.

⚙️ TEST TRUTH VALUE:
SHIPMENT #5001
delivered_date: NULL
(Order currently in transit)
→
EVALUATION RESULT
STANDBY
Select a comparison operator to test PostgreSQL 3-valued logic.
Rule: In SQL, NULL represents unknown or missing state — not a value, zero, or empty string. 3-VALUED LOGIC

Definition: IS NULL & IS NOT NULL

NULL means unknown, so it needs its own test

✖ The Trap: = NULL

Comparing anything with NULL gives UNKNOWN, never TRUE. WHERE x = NULL keeps no rows at all.

✓ The Fix: IS NULL

IS NULL is the one test that finds missing values: parcels not delivered, tickets not resolved.

🔗 The Inverse: IS NOT NULL

IS NOT NULL keeps only rows that have a value. Never write != NULL: it also returns nothing.

NULL checks on sales.shipments
PostgreSQL
TRAPThe trap: = NULL ▶ Run
SELECT shipment_id, order_id
FROM sales.shipments
WHERE delivered_date = NULL
LIMIT 10;
→ 0 rows, though 14,982 are missing
FIXThe fix: IS NULL ▶ Run
SELECT shipment_id, shipped_date
FROM sales.shipments
WHERE delivered_date IS NULL
LIMIT 10;
→ 14,982 of 1,04,987 still on the way
INVERSEIS NOT NULL ▶ Run
SELECT shipment_id, delivered_date
FROM sales.shipments
WHERE delivered_date IS NOT NULL
LIMIT 10;
→ 90,005 delivered: 90,005 + 14,982 = 1,04,987
65%

Query Mode: Unlocked — SELECT, WHERE & NULL

Time to test your knowledge! Solve real production challenges across RetailMart customer tiers, low-cost product pricing, and missing data audits.

🌱Arena 01: Row Selection

Key Takeaways: Row Filtering & Uniqueness

Core rules to commit to memory from Pillar 1.

🔍 1. Filter Early, Filter Hard

The earlier in the query pipeline rows are eliminated, the less memory and CPU required for subsequent processing steps. Always restrict rows with WHERE.

⚖️ 2. NULL Requires IS NULL

Never use col = NULL or col != NULL. In SQL three-valued logic, comparisons with NULL evaluate to UNKNOWN. Always write IS NULL or IS NOT NULL.

✨ 3. DISTINCT Operates on Tuples

DISTINCT evaluates the combination of every projected column. If you select customer_id, order_date, distinct applies to the pair together.

💡 PRO TIP: In PostgreSQL, column aliases created with AS cannot be referenced in the same query's WHERE clause because WHERE executes before SELECT.

Interview Scenario: SELECT * vs Named Columns

Why senior engineers and database architects reject SELECT * in production pull requests.

🔄 1. Network & Buffer I/O

Fetching unneeded text, JSON, or bytea columns forces PostgreSQL to read TOAST tables from disk and transfers massive payload volumes over the network wire.

⚡ 2. Breaks Index-Only Scans

If you query SELECT first_name, email, PostgreSQL can satisfy the query entirely from a covering B-Tree index without ever visiting the table heap. SELECT * forces heap lookups.

🛡️ 3. Schema Fragility

When columns are added or reordered during migrations, application code binding columns by positional index will silently break or map data into incorrect object fields.

MODEL INTERVIEW RESPONSE SUMMARY:

"In production APIs, we always specify explicit column lists. It minimizes disk I/O, enables index-only scans, reduces wire transfer latency, and decouples our application models from database schema changes."

Boolean Gates: AND, OR, NOT & Precedence

Why operator precedence breaks queries and how parentheses prevent disastrous logic leaks.

⚙️ EVALUATE LOGIC:
QUERY: city = 'Noida' OR city = 'Prayagraj' AND square_ft > 3000
NOIDA BRANCH: city = 'Noida'
7 Total Stores • 3 Large (>3,000 sq ft) • 4 Small (≤3,000 sq ft)
● WAITING EVALUATION
PRAYAGRAJ BRANCH: city = 'Prayagraj'
8 Total Stores • 2 Large (>3,000 sq ft) • 6 Small (≤3,000 sq ft)
● WAITING EVALUATION
Standby • Click a button to evaluate boolean precedence across RetailMart stores. READY

Definition: AND, OR, NOT & Precedence

Combine conditions, and put brackets where you mean them

🔗 1. AND: Both Must Be TRUE

A row stays only if every condition joined by AND is TRUE. NOT flips a condition.

🔀 2. OR: Either One Is Enough

A row stays if any condition joined by OR is TRUE.

⚠️ 3. AND Runs Before OR

A OR B AND C means A OR (B AND C). No error, just wrong rows. Mixing them? Add brackets.

AND, OR and brackets on stores.stores
PostgreSQL
STEP 1AND: both TRUE ▶ Run
SELECT store_id, city, square_ft
FROM stores.stores
WHERE city = 'Noida'
  AND square_ft > 3000
LIMIT 10;
→ 3 of Noida's 7 stores
TRAPNo brackets ▶ Run
SELECT store_id, city, square_ft
FROM stores.stores
WHERE city = 'Noida'
   OR city = 'Prayagraj'
  AND square_ft > 3000
LIMIT 10;
→ 9 rows: all 7 Noida + 2 large Prayagraj
FIXBrackets: what you meant ▶ Run
SELECT store_id, city, square_ft
FROM stores.stores
WHERE (city = 'Noida'
    OR city = 'Prayagraj')
  AND square_ft > 3000
LIMIT 10;
→ 5 rows: only the large stores of both

Pattern Scanner: LIKE, ILIKE & Wildcard Engine

String matching mechanics with % (multi-character) and _ (single-character) templates.

⚙️ TEST PATTERN:
PATTERN: SELECT EMAIL, FIRST_NAME FROM CUSTOMERS
Rahul Sharma
● QUEUED
Anita Desai
● QUEUED
Ankit Kumar
● QUEUED
Priya Kapoor
● QUEUED
Standby • Click a pattern template to analyze string wildcard matches. 4 / 4 ROWS QUEUED

Definition: LIKE, ILIKE, BETWEEN & IN

Match patterns, ranges and lists

🔍 1. LIKE vs ILIKE

% = any characters, _ = exactly one. LIKE cares about capital letters; ILIKE does not.

📏 2. BETWEEN Includes Both Ends

price BETWEEN 100 AND 500 means 100 ≤ price ≤ 500, both ends included.

📋 3. IN: One List

status IN ('Shipped', 'Delivered') says the same as two ORs, and cannot lose a bracket.

Patterns, ranges and lists on RetailMart
PostgreSQL
LIKEILIKE ignores capitals ▶ Run
SELECT first_name, email
FROM customers.customers
WHERE first_name ILIKE 'a%'
LIMIT 10;
→ ILIKE: 6,673 names; LIKE 'a%': 0
BETWEENBoth ends included ▶ Run
SELECT product_name, price
FROM products.products
WHERE price BETWEEN 100 AND 500
LIMIT 10;
→ 315 of 6,036 products, ₹100 to ₹500
INOne list, no OR chain ▶ Run
SELECT order_id, order_status
FROM sales.orders
WHERE order_status
      IN ('Shipped', 'Delivered')
LIMIT 10;
→ 97,522 orders: 14,982 + 82,540

BETWEEN with Timestamps & ILIKE Index Traps

Two subtle production defects that corrupt date reports and destroy database performance.

⚠️ 1. The Timestamp Midnight Trap

Writing BETWEEN '2025-01-01' AND '2025-01-31' expands to 2025-01-31 00:00:00. Any order placed after midnight on Jan 31st is silently dropped from your monthly revenue report!

✓ 2. The Production Solution

Always use half-open intervals: date >= '2025-01-01' AND date < '2025-02-01'. This cleanly covers every millisecond of January without missing boundary records.

🚀 3. ILIKE Index Overhead

A leading wildcard like ILIKE '%sharma' cannot use a standard B-Tree index and triggers a full table scan. For high-throughput search, create a trigram index with pg_trgm.

💡 PRO TIP: In PostgreSQL, prefix wildcards like LIKE 'Sharma%' CAN use standard B-Tree indexes with text pattern ops: CREATE INDEX idx_name ON table(col text_pattern_ops);
65%

Query Mode: Unlocked — Compound Conditions & Patterns

Time to test your knowledge! Tackle Gmail customer filters, order timestamp ranges, the live AND/OR precedence demo, and complex multi-filter investigations.

⚒Arena 02: Compound Logic

Key Takeaways: Logical Operators & Patterns

Core rules to commit to memory from Pillar 2.

🔗 1. Parenthesize Mixed Logic

Never write mixed AND and OR expressions without explicit parentheses. AND always binds tighter and will silently distort business filtering rules.

📅 2. Never Use BETWEEN for Dates

Because dates contain timestamps with time components, write half-open intervals with >= and < to prevent boundary record omission.

🔍 3. Wildcards Dictate Indexes

Prefix matching ('Sharma%') can use a B-Tree index. Leading wildcards ('%sharma') cannot, and need a Trigram GIN index for production speed.

💡 GOLDEN RULE: When checking discrete lists, prefer col IN (v1, v2, v3) over chained OR predicates — it generates cleaner plans and concise code.

Interview Scenario: LIKE vs ILIKE vs Full-Text Search

When to use pattern wildcards, trigram indexes, or dedicated lexical search engines.

🔍 1. LIKE / ILIKE

Best for simple string matching, prefix searches (e.g. autocompleting country codes), and exact pattern checking. Low overhead but limited linguistic intelligence.

🧭 2. pg_trgm (Trigram GIN)

Splits words into 3-character slices. Enables sub-second ILIKE '%term%' substring searches and fuzzy typo-tolerant matching across lakhs of rows.

📚 3. Full-Text Search (tsvector)

Parses text into normalized lexemes, strips stop words ('the', 'and'), stems word forms ('running' → 'run'), and ranks results by relevance with ts_rank.

MODEL INTERVIEW RESPONSE:

"Use B-Tree LIKE for known prefixes. Use pg_trgm for arbitrary substring lookups. Migrate to PostgreSQL Full-Text Search (tsvector/tsquery) whenever users search free-form natural language documents requiring stemming and relevance ranking."

Interview Studio: Filtering, NULL & Patterns

Questions interviewers really ask about today’s topic, with the answer and the trap.

TOP INTERVIEW QUESTIONS
NULL • THREE-VALUED LOGIC

“Why does WHERE delivered_date = NULL return no rows, and what do you write instead?”

✓ MODEL ANSWER:
NULL means “unknown”, so any comparison with it (=, !=, <, >) gives UNKNOWN, not TRUE. WHERE keeps only rows that are TRUE, so = NULL keeps nothing. Write IS NULL (or IS NOT NULL). On RetailMart’s sales.shipments, delivered_date = NULL finds 0 rows while delivered_date IS NULL finds every parcel still on the way.
🧠 WHY INTERVIEWERS ASK THIS:

Checks that you understand NULL as “unknown”, not as zero or an empty string: the base of every data-quality question.

⚠️ COMMON TRAP TO AVOID:

Writing != NULL to find filled-in values. It also returns 0 rows: use IS NOT NULL.

DISTINCT & Filtering Self-Check

Close your notes. Answer from memory. Click any card to reveal the verified answer.

1. What does the query WHERE balance = NULL return?
Zero rows. Comparing anything with NULL gives UNKNOWN, and WHERE keeps only TRUE rows. Write WHERE balance IS NULL.
2. Does DISTINCT col1, col2 deduplicate col1 alone or the combination?
The combination. A row is dropped only when both col1 and col2 match a row already in the result.
3. Which stores does WHERE city = 'Noida' OR city = 'Prayagraj' AND square_ft > 3000 return?
All Noida stores of any size, plus the large Prayagraj ones, because AND runs before OR. Brackets around the OR part give only the large stores of both cities.
4. What does first_name LIKE 'A___%' match?
Names that start with a capital A and have at least 4 letters: A, then exactly three characters (___), then anything (%). “Arun” and “Ananya” match; “Ali” does not; “aditi” does not (LIKE is case-sensitive).
5. Why is BETWEEN '2025-03-01' AND '2025-03-31' risky on a timestamp column?
The upper end means 2025-03-31 00:00:00, so everything later on 31 March is left out. Write >= '2025-03-01' AND < '2025-04-01'. (On a DATE column such as sales.orders.order_date BETWEEN is safe.)
6. Write city = 'Agra' OR city = 'Kanpur' OR city = 'Noida' in a shorter way.
city IN ('Agra', 'Kanpur', 'Noida'). Same rows, shorter, and no chance of a missing bracket when you add an AND later.

The 6 Golden Laws Bento

The rules to remember from today, for every WHERE you will ever write.

🛡️ LAW 01 • 3-VALUED LOGIC

NULL Is Unknown, Not a Value

Never write = NULL or != NULL: both give UNKNOWN and drop every row. Write IS NULL or IS NOT NULL.

⚡ IS NULL is the only test that works on NULL.
⚖️ LAW 02 • LOGIC PRECEDENCE

Brackets Around Every OR

AND runs before OR. Without brackets, A OR B AND C means A OR (B AND C) and silently lets wrong rows in.

⚠️ Mixing AND with OR? Add brackets.
📅 LAW 03 • DATE RANGES

Half-Open Ranges on Timestamps

On a timestamp column, write >= start AND < next_start. BETWEEN stops at midnight of the last day and drops the rest of it.

📅 Half-open ranges never miss the last day.
📋 LAW 04 • SET MEMBERSHIP

IN Instead of OR Chains

city IN ('Agra', 'Kanpur', 'Noida') says the same as three ORs, reads better, and cannot lose a bracket when you add an AND.

✔️ One list, one condition.
🔍 LAW 05 • PATTERNS

ILIKE for Case, Fixed Start for Speed

LIKE is case-sensitive, ILIKE is not. % = any characters, _ = exactly one. A leading % makes PostgreSQL read every row.

🚀 'Sharma%' can use an index; '%sharma' cannot.
✨ LAW 06 • DEDUPLICATION

DISTINCT Covers the Whole Row

SELECT DISTINCT city, state removes a row only when every selected column matches. It costs a sort or hash step, so never use it to hide a wrong result.

🔍 Find why rows repeat before reaching for DISTINCT.

DISTINCT & Filtering Quick Reference Studio

Every pattern from today as a real RetailMart query: run it, copy it, change it.

DISTINCT & Filtering Cheat Sheet
SQL REFERENCE
-- FILTERING & PATTERNS
-- Comparison + set membership (IN)▶ Run
SELECT order_id, net_total FROM sales.orders
WHERE net_total >= 5000
  AND order_status IN ('Shipped', 'Delivered') LIMIT 10;
-- Missing value: IS NULL▶ Run
SELECT ticket_id, category FROM support.tickets
WHERE resolved_date IS NULL LIMIT 10;
-- Value present: IS NOT NULL▶ Run
SELECT shipment_id, delivered_date FROM sales.shipments
WHERE delivered_date IS NOT NULL LIMIT 10;
-- Case-insensitive pattern: ILIKE▶ Run
SELECT first_name, email FROM customers.customers
WHERE email ILIKE '%@gmail.com' LIMIT 10;
-- One character per _ : LIKE▶ Run
SELECT first_name, last_name FROM customers.customers
WHERE first_name LIKE 'A___%' LIMIT 10;
-- RANGES, LOGIC & DEDUPLICATION
-- Inclusive range: BETWEEN▶ Run
SELECT product_name, price FROM products.products
WHERE price BETWEEN 100 AND 500 LIMIT 10;
-- Timestamp range: half-open▶ Run
SELECT event_id, event_timestamp FROM web_events.events
WHERE event_timestamp >= '2025-03-01'
  AND event_timestamp < '2025-04-01' LIMIT 10;
-- AND + OR: brackets first▶ Run
SELECT store_id, city, square_ft FROM stores.stores
WHERE (city = 'Noida' OR city = 'Prayagraj')
  AND square_ft > 3000 LIMIT 10;
-- Leave values out: NOT IN▶ Run
SELECT order_id, order_status FROM sales.orders
WHERE order_status NOT IN ('Cancelled', 'Returned') LIMIT 10;
-- Unique combinations: DISTINCT▶ Run
SELECT DISTINCT city, state FROM customers.addresses
ORDER BY state, city LIMIT 10;

Take-Home Challenge: RetailMart Filtering Report

Do these 4 drills on RetailMart in your own PostgreSQL before the next class.

🎯 400 practice questions for this session · Easy to Crazy hard, run and checked on the pagePRACTICE →
🎯 THE 4-STAGE FILTERING SPRINT:
Stage 1 — Customer Tier & Metro Filter

Query customers.customers for all Gold and Silver customers who registered in 2025 (registration_date >= '2025-01-01' AND < '2026-01-01'). Then list the default addresses (is_default = TRUE) in Mumbai, Delhi or Bengaluru from customers.addresses, once with IN and once with ORs in brackets.

Stage 2 — Undelivered Shipment Backlog

Find all shipments in sales.shipments where delivered_date IS NULL. Then run the same query with = NULL and write down why the two results differ.

Stage 3 — Deduplication

Find every unique combination of state and city in customers.addresses (default addresses only). Then list the distinct cities in stores.stores that have a store larger than 3,000 sq ft (square_ft).

Stage 4 — Closed, Never Resolved

In support.tickets, find the tickets with status = 'Closed' but no resolved_date, then the DISTINCT categories they belong to. Last: the Open tickets in 'Payment Failure' or 'Login Issue', written once with IN and once with OR in brackets: both must return the same rows.

Master Curriculum Journey Roadmap

🏁THESHIRAVERSE SQL PATH
✓ SESSION 01
What is SQL?
Relational Model • Port 5432 Server • 5 SQL Families
2 more
✓ SESSION 04
Data Types
NUMERIC vs FLOAT • INT / DATE / TIMESTAMPTZ • ALTER ... USING
2 more
★ SESSION 07 • YOU ARE HERE
DISTINCT & Filtering
WHERE • DISTINCT • IS NULL • AND / OR / NOT • LIKE / BETWEEN / IN
→
➜ NEXT • SESSION 08
Sorting & Pagination
ORDER BY • NULLS FIRST / LAST • LIMIT / OFFSET • Execution order
50 more
🏁 SESSION 59 • FINISH LINE
SQL for BI Tools & Dashboards
Module 6 • Analyst Patterns • the finish line

59 sessions, from zero to job-ready. Today is session 7.

Next Session: Sorting & Pagination

NEXT MISSION • MODULE 1 • SESSION 08
Sorting & Pagination: ORDER BY, LIMIT & OFFSET

Today you picked the right rows. Next class puts them in the right order and hands them out one page at a time, the way every shopping app and feed does.

📊
1. ORDER BY & NULLs

Sort by one or many columns, and decide where the missing values go with NULLS FIRST / NULLS LAST.

📄
2. LIMIT & OFFSET

Show 20 rows per page, jump to page 3, and see why page 5,000 is slow.

⚙️
3. Execution Order

Why an alias works in ORDER BY but fails in WHERE: the order PostgreSQL really runs a query in.

Live class schedule & notes: Sorting & Pagination →
NEXT UP • MODULE 1 • SESSION 08
→ next   ← back   F fullscreen   H hide bars   N notes
1 / 31