Skip to Content

Learn MySql

MySql
22 November 2025 by
Learn MySql
DATA REVOLUTION CONSULTING GROUP

seamlessly.

Sample schema (MySQL) — use for all questions

-- Customers customers(customer_id INT PRIMARY KEY, name VARCHAR(100), email VARCHAR(100), city VARCHAR(50), created_at DATE); -- Products products(product_id INT PRIMARY KEY, name VARCHAR(100), category VARCHAR(50), price DECIMAL(10,2), supplier_id INT); -- Orders orders(order_id INT PRIMARY KEY, customer_id INT, order_date DATE, status VARCHAR(20), total DECIMAL(12,2)); -- Order items order_items(item_id INT PRIMARY KEY, order_id INT, product_id INT, quantity INT, unit_price DECIMAL(10,2)); -- Employees employees(employee_id INT PRIMARY KEY, name VARCHAR(100), dept_id INT, hire_date DATE, salary DECIMAL(12,2)); -- Departments departments(dept_id INT PRIMARY KEY, dept_name VARCHAR(50)); -- Suppliers suppliers(supplier_id INT PRIMARY KEY, supplier_name VARCHAR(100), country VARCHAR(50));

50 SQL questions & answers (MySQL 8+)

Basics (1–10)

  1. Q: List all customers.

    A:

    SELECT * FROM customers;

    Returns all customer rows.

  2. Q: Select customer names and emails.

    A:

    SELECT name, email FROM customers;

  3. Q: Find customers in city 'Mumbai'.

    A:

    SELECT * FROM customers WHERE city = 'Mumbai';

  4. Q: Count total number of customers.

    A:

    SELECT COUNT(*) AS total_customers FROM customers;

  5. Q: List distinct product categories.

    A:

    SELECT DISTINCT category FROM products;

  6. Q: Get orders placed after 2024-01-01.

    A:

    SELECT * FROM orders WHERE order_date > '2024-01-01';

  7. Q: Show order details for order_id = 101.

    A:

    SELECT o.*, oi.* FROM orders o JOIN order_items oi ON o.order_id = oi.order_id WHERE o.order_id = 101;

  8. Q: Insert a new product.

    A:

    INSERT INTO products (product_id, name, category, price, supplier_id) VALUES (501, 'Notebook', 'Stationery', 59.99, 10);

  9. Q: Update a customer's city.

    A:

    UPDATE customers SET city = 'Bengaluru' WHERE customer_id = 12;

  10. Q: Delete an order (and its items).

    A:

    START TRANSACTION; DELETE FROM order_items WHERE order_id = 200; DELETE FROM orders WHERE order_id = 200; COMMIT;

Intermediate (11–25)

  1. Q: Total sales (sum of orders total).

    A:

    SELECT SUM(total) AS total_sales FROM orders;

  2. Q: Total sales by month.

    A:

    SELECT DATE_FORMAT(order_date, '%Y-%m') AS month, SUM(total) AS sales FROM orders GROUP BY month ORDER BY month;

  3. Q: Top 5 products by quantity sold.

    A:

    SELECT p.product_id, p.name, SUM(oi.quantity) AS total_qty FROM products p JOIN order_items oi ON p.product_id = oi.product_id GROUP BY p.product_id, p.name ORDER BY total_qty DESC LIMIT 5;

  4. Q: Customers who never placed an order.

    A:

    SELECT c.* FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id WHERE o.order_id IS NULL;

  5. Q: Average order value.

    A:

    SELECT AVG(total) AS avg_order_value FROM orders;

  6. Q: Orders with total > average order.

    A:

    SELECT * FROM orders WHERE total > (SELECT AVG(total) FROM orders);

  7. Q: Quantity and revenue for each order item.

    A:

    SELECT oi.order_id, oi.product_id, oi.quantity, (oi.quantity * oi.unit_price) AS revenue FROM order_items oi;

  8. Q: Product price increase by 10% for category 'Electronics'.

    A:

    UPDATE products SET price = price * 1.10 WHERE category = 'Electronics';

  9. Q: Get last order date per customer.

    A:

    SELECT customer_id, MAX(order_date) AS last_order FROM orders GROUP BY customer_id;

  10. Q: Use CASE to classify orders as 'Small', 'Medium', 'Large'.

    A:

    SELECT order_id, total, CASE WHEN total < 100 THEN 'Small' WHEN total BETWEEN 100 AND 500 THEN 'Medium' ELSE 'Large' END AS size FROM orders;

  11. Q: Find products with price between 50 and 200.

    A:

    SELECT * FROM products WHERE price BETWEEN 50 AND 200;

  12. Q: Customers count per city (having > 5).

    A:

    SELECT city, COUNT(*) AS customers FROM customers GROUP BY city HAVING COUNT(*) > 5;

  13. Q: Create a view for monthly sales summary.

    A:

    CREATE VIEW monthly_sales AS SELECT DATE_FORMAT(order_date, '%Y-%m') AS month, SUM(total) AS sales FROM orders GROUP BY month;

  14. Q: Use a common table expression (CTE) for top customers by sales.

    A:

    WITH cust_sales AS ( SELECT customer_id, SUM(total) AS total_spent FROM orders GROUP BY customer_id ) SELECT c.customer_id, c.name, cs.total_spent FROM cust_sales cs JOIN customers c ON cs.customer_id = c.customer_id ORDER BY cs.total_spent DESC;

  15. Q: Combine product name and category as single column.

    A:

    SELECT CONCAT(name, ' (', category, ')') AS product_label FROM products;

Advanced joins & subqueries (26–35)

  1. Q: Orders with product names (flatten one row per item).

    A:

    SELECT o.order_id, o.order_date, c.name AS customer, p.name AS product, oi.quantity, oi.unit_price FROM orders o JOIN customers c ON o.customer_id = c.customer_id JOIN order_items oi ON o.order_id = oi.order_id JOIN products p ON oi.product_id = p.product_id;

  2. Q: Customers and their total order count & total spent.

    A:

    SELECT c.customer_id, c.name, COUNT(o.order_id) AS orders_count, COALESCE(SUM(o.total),0) AS total_spent FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id GROUP BY c.customer_id, c.name;

  3. Q: Orders that include at least one product from supplier_id = 5.

    A:

    SELECT DISTINCT o.order_id FROM orders o JOIN order_items oi ON o.order_id = oi.order_id JOIN products p ON oi.product_id = p.product_id WHERE p.supplier_id = 5;

  4. Q: Find customers who bought all products in a given category (set division).

    A:

    -- Customers who purchased every product in category 'Books' SELECT c.customer_id, c.name FROM customers c WHERE NOT EXISTS ( SELECT 1 FROM products p WHERE p.category = 'Books' AND NOT EXISTS ( SELECT 1 FROM order_items oi JOIN orders o ON oi.order_id = o.order_id WHERE o.customer_id = c.customer_id AND oi.product_id = p.product_id ) );

  5. Q: Top product per month by revenue (use window functions).

    A:

    SELECT month, product_id, name, revenue FROM ( SELECT DATE_FORMAT(o.order_date, '%Y-%m') AS month, p.product_id, p.name, SUM(oi.quantity * oi.unit_price) AS revenue, ROW_NUMBER() OVER (PARTITION BY DATE_FORMAT(o.order_date, '%Y-%m') ORDER BY SUM(oi.quantity * oi.unit_price) DESC) AS rn FROM orders o JOIN order_items oi ON o.order_id = oi.order_id JOIN products p ON oi.product_id = p.product_id GROUP BY month, p.product_id, p.name ) t WHERE rn = 1;

  6. Q: Find second highest salary in employees.

    A:

    SELECT MAX(salary) AS second_highest FROM employees WHERE salary < (SELECT MAX(salary) FROM employees);

  7. Q: Rank employees by salary within department.

    A:

    SELECT e.employee_id, e.name, e.dept_id, e.salary, RANK() OVER (PARTITION BY e.dept_id ORDER BY e.salary DESC) AS dept_rank FROM employees e;

  8. Q: Cumulative sales by date.

    A:

    SELECT order_date, SUM(total) AS daily_sales, SUM(SUM(total)) OVER (ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_sales FROM orders GROUP BY order_date ORDER BY order_date;

  9. Q: Delete duplicate customers keeping the lowest customer_id.

    A:

    DELETE c1 FROM customers c1 INNER JOIN customers c2 ON c1.email = c2.email AND c1.customer_id > c2.customer_id;

  10. Q: Find orders where any item quantity > 100 (exists).

    A:

    SELECT o.* FROM orders o WHERE EXISTS ( SELECT 1 FROM order_items oi WHERE oi.order_id = o.order_id AND oi.quantity > 100 );

Performance, indexing & optimization (36–42)

  1. Q: Create an index to speed up orders by customer_id and order_date.

    A:

    CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);

  2. Q: Show query execution plan for a slow query.

    A:

    EXPLAIN SELECT * FROM orders o JOIN customers c ON o.customer_id = c.customer_id WHERE o.order_date > '2024-01-01';

  3. Q: Rewrite a correlated subquery to a JOIN (example).

    A:

    -- correlated subquery SELECT o.order_id, o.total FROM orders o WHERE o.total > (SELECT AVG(total) FROM orders); -- equivalent with JOIN + derived SELECT o.order_id, o.total FROM orders o JOIN (SELECT AVG(total) AS avg_total FROM orders) a ON o.total > a.avg_total;

  4. Q: Partitioned queries concept (example creating range partition by year).

    A:

    CREATE TABLE orders_y ( order_id INT PRIMARY KEY, customer_id INT, order_date DATE, total DECIMAL(12,2) ) PARTITION BY RANGE (YEAR(order_date)) ( PARTITION p2022 VALUES LESS THAN (2023), PARTITION p2023 VALUES LESS THAN (2024), PARTITION pmax VALUES LESS THAN MAXVALUE );

  5. Q: Use ANALYZE TABLE to update optimizer statistics.

    A:

    ANALYZE TABLE orders;

  6. Q: Use OPTIMIZE TABLE to reclaim space after large deletes.

    A:

    OPTIMIZE TABLE order_items;

  7. Q: Identify missing index suggestions using performance_schema or EXPLAIN — simple guideline.

    A:

    Use EXPLAIN to see full table scans; add indexes on columns used in WHERE, JOIN, ORDER BY. (No single SQL answer — check EXPLAIN output.)

Advanced features, JSON, regex, security (43–50)

  1. Q: Store product attributes as JSON and query them.

    A:

    -- product table with json column ALTER TABLE products ADD COLUMN attrs JSON; -- query products where attrs->>'$.color' = 'red' SELECT * FROM products WHERE JSON_UNQUOTE(JSON_EXTRACT(attrs, '$.color')) = 'red';

  2. Q: Aggregate product names as comma-separated list per order.

    A:

    SELECT o.order_id, GROUP_CONCAT(p.name SEPARATOR ', ') AS products FROM orders o JOIN order_items oi ON o.order_id = oi.order_id JOIN products p ON oi.product_id = p.product_id GROUP BY o.order_id;

  3. Q: Use regular expressions to find emails from a specific domain.

    A:

    SELECT * FROM customers WHERE email REGEXP '@example\\.com$';

  4. Q: Implement a stored procedure to add an order (simplified).

    A:

    DELIMITER // CREATE PROCEDURE add_order(IN cid INT, IN odate DATE, IN total_val DECIMAL(12,2)) BEGIN INSERT INTO orders (customer_id, order_date, total) VALUES (cid, odate, total_val); END // DELIMITER ;

  5. Q: Use transactions with rollback on error (pseudo).

    A:

    START TRANSACTION; INSERT INTO orders (...) VALUES (...); INSERT INTO order_items (...) VALUES (...); -- if error: ROLLBACK; else COMMIT; COMMIT;

  6. Q: Row-level locking for update to avoid race condition.

    A:

    START TRANSACTION; SELECT stock FROM products WHERE product_id = 10 FOR UPDATE; -- update stock after checks UPDATE products SET stock = stock - 1 WHERE product_id = 10; COMMIT;

  7. Q: Create a pivot table via SQL: monthly sales per category.

    A:

    SELECT month, SUM(CASE WHEN category = 'Electronics' THEN revenue ELSE 0 END) AS Electronics, SUM(CASE WHEN category = 'Books' THEN revenue ELSE 0 END) AS Books, SUM(revenue) AS Total FROM ( SELECT DATE_FORMAT(o.order_date, '%Y-%m') AS month, p.category, SUM(oi.quantity * oi.unit_price) AS revenue FROM orders o JOIN order_items oi ON o.order_id = oi.order_id JOIN products p ON oi.product_id = p.product_id GROUP BY month, p.category ) t GROUP BY month ORDER BY month;

  8. Q: Use LAG to compute month-over-month change for sales.

    A:

    WITH monthly AS ( SELECT DATE_FORMAT(order_date, '%Y-%m') AS month, SUM(total) AS sales FROM orders GROUP BY month ) SELECT month, sales, LAG(sales) OVER (ORDER BY month) AS prev_sales, sales - LAG(sales) OVER (ORDER BY month) AS diff, CASE WHEN LAG(sales) OVER (ORDER BY month) = 0 THEN NULL ELSE (sales - LAG(sales) OVER (ORDER BY month)) / LAG(sales) OVER (ORDER BY month) END AS pct_change FROM monthly;

in Blog