Core Statement

The SELECT Statement

SELECT is the first word in almost every SQL query. It tells the database which columns you want to retrieve. Understanding it deeply is the foundation of all SQL.

SQL — SELECT
— Select all columns (use sparingly in production)
SELECT * FROM orders;
 
— Select specific columns (always preferred)
SELECT order_id, customer_name, order_amount
FROM orders;
 
— Calculated columns
SELECT order_id,
  order_amount,
  order_amount * 0.18 AS gst_amount,
  order_amount + (order_amount * 0.18) AS total_with_gst
FROM orders;
Best practice: Always name specific columns instead of SELECT *. It’s faster, safer when table structure changes, and shows interviewers you write production-quality SQL.
  • SELECT specifies which columns to return — columns are comma-separated
  • SELECT * returns ALL columns — avoid in production but fine for exploration
  • AS creates an alias — a readable name for any column or expression
  • Calculated columns (e.g. price * quantity) can be created directly in SELECT
Filtering

WHERE — Filtering Rows

WHERE filters which rows are included in results. Only rows where the condition evaluates to TRUE are returned. This is the most important SQL concept for analysts — most questions require filtering data.

OperatorMeaningExample
=Equals exactlycity = 'Mumbai'
!= or <>Not equalstatus != 'cancelled'
>, <, >=, <=Comparisonamount > 5000
INMatch any in listcity IN ('Mumbai','Delhi')
NOT INNot in liststatus NOT IN ('returned')
BETWEENRange (inclusive)date BETWEEN '2024-01-01' AND '2024-03-31'
LIKEPattern matchname LIKE 'Raj%'
IS NULLCheck for missingemail IS NULL
IS NOT NULLCheck not missingphone IS NOT NULL
SQL — WHERE Examples
— Simple condition
SELECT * FROM orders WHERE order_amount > 10000;
 
— AND / OR: combine conditions
SELECT * FROM orders
WHERE region = ‘North’ AND order_amount > 5000;
 
— IN: cleaner than many OR conditions
SELECT * FROM customers
WHERE city IN (‘Mumbai’, ‘Delhi’, ‘Bengaluru’);
 
— LIKE with wildcards: % = any chars, _ = one char
SELECT * FROM products
WHERE product_name LIKE ‘%phone%’;
 
— BETWEEN: inclusive on both ends
SELECT * FROM orders
WHERE order_date BETWEEN ‘2024-01-01’ AND ‘2024-03-31’;
Interview tip: LIKE ‘%text%’ finds text anywhere in a string. ‘Raj%’ matches strings starting with Raj. ‘%pur’ matches strings ending with pur. LIKE is case-insensitive in MySQL but case-sensitive in PostgreSQL.
Sorting

ORDER BY and LIMIT

ORDER BY sorts results. LIMIT restricts how many rows you get back. Together they power “find the top N” — one of the most common interview patterns.

SQL — ORDER BY & LIMIT
— Descending: highest first
SELECT customer_name, order_amount
FROM orders
ORDER BY order_amount DESC
LIMIT 10;
 
— Multiple columns: sort by region, then by amount within each region
SELECT region, customer_name, order_amount
FROM orders
ORDER BY region ASC, order_amount DESC;
 
— OFFSET: skip first N rows (pagination)
SELECT * FROM products
ORDER BY price DESC
LIMIT 10 OFFSET 20; — rows 21-30
Remember: ASC is the default sort direction so you rarely need to write it. Always write DESC explicitly when you want highest/latest first. LIMIT without ORDER BY gives random rows — always pair them.
Deduplication

DISTINCT — Remove Duplicates

SQL — DISTINCT
— Get unique cities from customers table
SELECT DISTINCT city FROM customers;
 
— Count unique customers who placed orders
SELECT COUNT(DISTINCT customer_id) AS unique_customers
FROM orders;
 
— DISTINCT across multiple columns
SELECT DISTINCT region, category
FROM sales
ORDER BY region;
Interview usage: COUNT(DISTINCT column) is extremely common — it answers ‘how many unique customers/products/users’ questions. Always think DISTINCT when the question uses ‘unique’ or ‘distinct’.
Missing Data

Handling NULL Values

NULL means a value is missing or unknown. It is not zero, not empty string — it’s the absence of data. Understanding NULL is critical for real-world data analyst work.

SQL — NULL Handling
— Find rows with missing email
SELECT * FROM customers WHERE email IS NULL;
 
— Find rows where email exists
SELECT * FROM customers WHERE email IS NOT NULL;
 
— COALESCE: replace NULL with a default value
SELECT customer_name,
  COALESCE(email, ‘no-email@unknown.com’) AS email
FROM customers;
 
— NULLIF: returns NULL if two values are equal
— Use to avoid division by zero errors
SELECT revenue / NULLIF(orders, 0) AS avg_order_value
FROM daily_stats;
Critical rule: NULL = NULL is UNKNOWN in SQL — not TRUE. You MUST use IS NULL / IS NOT NULL. Doing WHERE col = NULL will always return zero rows. This is a very common beginner mistake tested in interviews.
Readability

Column & Table Aliases

SQL — Aliases
— Column alias with AS (AS is optional)
SELECT
  customer_name AS name,
  COUNT(*) AS total_orders,
  SUM(amount) AS revenue
FROM orders
GROUP BY customer_name;
 
— Table alias: shortens joins significantly
SELECT c.customer_name, o.order_amount
FROM customers c
JOIN orders o ON c.id = o.customer_id;
Best practice: Always use short table aliases (c, o, e) when joining tables — it makes queries dramatically more readable. This is something interviewers notice and appreciate.
Interview Questions

Practice Questions — SQL Basics

Easy
Write a query to find all customers from Mumbai who placed orders over ₹5,000.
InfosysTCSWipro
+
Use WHERE with AND to combine both conditions. Always filter the table that has the data — here the orders table has order_amount and customers has city, so you’d join first or filter on the relevant columns.
SELECT c.customer_name, o.order_amount
FROM customers c
JOIN orders o ON c.id = o.customer_id
WHERE c.city = ‘Mumbai’ AND o.order_amount > 5000;
Easy
Find all products whose name contains the word ‘phone’ (case insensitive).
FlipkartMeesho
+
Use LIKE with % wildcards on both sides to find the word anywhere in the string. In PostgreSQL use ILIKE for case-insensitive matching.
SELECT * FROM products
WHERE product_name LIKE ‘%phone%’;

— PostgreSQL (case insensitive):
WHERE product_name ILIKE ‘%phone%’
Medium
List the top 5 most expensive products in each category.
AmazonPaytm
+
Use ORDER BY with LIMIT for a single category. For all categories at once, you need a window function — RANK() OVER (PARTITION BY category ORDER BY price DESC).
— Simple: top 5 overall
SELECT * FROM products ORDER BY price DESC LIMIT 5;

— Per category (window function):
WITH ranked AS (SELECT *, RANK() OVER(PARTITION BY category ORDER BY price DESC) rn FROM products)
SELECT * FROM ranked WHERE rn <= 5;

Ready to practice SQL with a mentor?

Book a free 1-on-1 SQL mock interview. Real questions, live feedback, written report.

Book Free Session