Free Study Material
This chapter moves beyond SELECT's basics into SQL's built-in functions — starting with the ones that do arithmetic on a number.
x raised to the power y.x to d decimal places.x is divided by y, the SQL equivalent of Python's %.SELECT POWER(2, 3);
SELECT ROUND(85.6789, 2);
SELECT MOD(17, 5);
POWER(2, 3) returns 8 (2 × 2 × 2). ROUND(85.6789, 2) returns 85.68 — rounded to two decimal places. MOD(17, 5) returns 2 — the remainder after 17 divides by 5 three whole times (15), leaving 2.
Note:ROUND(x, 0)rounds to a whole number, still displayed with SQL's own formatting — it doesn't changex's underlying data type the way a cast would.
These three functions do genuinely different jobs: POWER computes a new value from an exponent, ROUND reduces a value's precision for display, and MOD extracts specifically the remainder — the same remainder-finding idea Python's % already taught you, just written as a function call in SQL instead of an operator.
POWER(x, y) computes x to the power y; ROUND(x, d) rounds to d decimal places; MOD(x, y) returns the remainder of x divided by y — SQL's built-in math functions, called directly inside a query.
System Update: SQL Engine Ready.
Action: Run the blocks below. We will create a `NUMBERS` table to test our math functions.
These functions take numerical values as input and return a calculated result.
| Function | Description | Example |
|---|---|---|
| POWER(x, y) | Calculates x raised to the power of y. | POWER(2, 3) → 8 |
| ROUND(x, d) | Rounds number x to d decimal places. | ROUND(10.589, 1) → 10.6 |
| MOD(x, y) | Returns the Remainder when x is divided by y. | MOD(10, 3) → 1 |
/* ==================================================
SYSTEM SETUP (Creating Dummy Data)
================================================== */
DROP TABLE IF EXISTS NUMBERS;
CREATE TABLE NUMBERS (A INT, B INT, Price DECIMAL(10,3));
INSERT INTO NUMBERS VALUES (2, 3, 50.456);
INSERT INTO NUMBERS VALUES (10, 2, 99.123);
INSERT INTO NUMBERS VALUES (5, 3, 12.999);
/* ==================================================
TASK: Apply Math Functions
================================================== */
SELECT
A,
B,
POWER(A, B) AS Power_Result, -- 2^3 = 8
Price,
ROUND(Price, 1) AS Rounded_Price -- 50.456 -> 50.5
FROM NUMBERS;
/* ==================================================
SYSTEM SETUP
================================================== */
DROP TABLE IF EXISTS CALC;
CREATE TABLE CALC (Num1 INT, Num2 INT);
INSERT INTO CALC VALUES (10, 3);
INSERT INTO CALC VALUES (20, 4);
INSERT INTO CALC VALUES (25, 7);
/* ==================================================
TASK: Calculate Remainder
Note: In some SQL engines (like MySQL), we use MOD(a,b).
In SQLite/Postgres, we often use the % symbol (Num1 % Num2).
Below is the standard syntax.
================================================== */
SELECT
Num1,
Num2,
Num1 % Num2 AS Remainder -- Using % symbol for broad compatibility
FROM CALC;
What happens if the second number in ROUND(n, d) is Negative?
It starts rounding numbers to the Left of the decimal point!
Think of it as "Zeroing out" the last digits.
This topic covers SQL's built-in functions for text — changing case, measuring length, and removing unwanted surrounding spaces.
text.SELECT UPPER(Name) FROM STUDENT WHERE RollNo = 1;
SELECT LENGTH(Name) FROM STUDENT WHERE RollNo = 1;
SELECT TRIM(' Aisha ');
UPPER(Name) for Aisha's row returns 'AISHA'. LENGTH(Name) for the same row returns 5 — the number of characters in "Aisha". TRIM(' Aisha ') returns 'Aisha', with the surrounding spaces removed.
Note: These functions can be used directly on a literal value (likeTRIM(' Aisha ')above) or on a column from a table — both are valid, exactly like Python'sstrmethods work the same way on a literal string or a variable holding one.
TRIM() matters more than it looks: data typed by hand into a form often carries accidental extra spaces, which would make WHERE Name = 'Aisha' fail to match a stored 'Aisha ' with a trailing space — TRIM() is exactly the tool for cleaning that up before comparing or displaying text.
UPPER()/LOWER() convert case; LENGTH() counts characters; TRIM() removes leading and trailing spaces — SQL's basic text-cleaning functions, usable on a column or a literal string alike.
System Update: SQL Engine Ready.
Action: Run the blocks below to learn how to manipulate strings.
These functions are used to standardize text (e.g., making all emails lowercase) or check validity (e.g., is the password long enough?).
| Function | Description | Example |
|---|---|---|
| UPPER(str) or UCASE() |
Converts text to CAPITAL LETTERS. | UPPER('amit') → 'AMIT' |
| LOWER(str) or LCASE() |
Converts text to small letters. | LOWER('AMIT') → 'amit' |
| LENGTH(str) | Counts the number of characters (including spaces). | LENGTH('Hi You') → 6 |
/* ==================================================
SYSTEM SETUP (Messy Data)
================================================== */
DROP TABLE IF EXISTS USERS;
CREATE TABLE USERS (Name VARCHAR(20), Email VARCHAR(30));
INSERT INTO USERS VALUES ('Amit Kumar', 'AMIT@GMAIL.COM');
INSERT INTO USERS VALUES ('ravi sharma', 'Ravi.S@Yahoo.com');
/* ==================================================
TASK: Standardize Display
================================================== */
SELECT
UPPER(Name) AS Clean_Name, -- 'AMIT KUMAR'
LOWER(Email) AS Clean_Email, -- 'amit@gmail.com'
LENGTH(Name) AS Name_Length -- 10
FROM USERS;
Sometimes users accidentally type a space before or after their name (e.g., " Amit"). This causes issues because " Amit" != "Amit".
We use Trim functions to fix this.
/* ==================================================
SYSTEM SETUP (Dirty Data with Spaces)
Notice the spaces inside the quotes
================================================== */
DROP TABLE IF EXISTS DATA;
CREATE TABLE DATA (TextVal VARCHAR(20));
INSERT INTO DATA VALUES (' Ravi '); -- 3 spaces left, 3 spaces right
/* ==================================================
TASK: Compare Lengths
================================================== */
SELECT
TextVal,
LENGTH(TextVal) AS Original_Len, -- Should be 3+4+3 = 10
TRIM(TextVal) AS Cleaned_Text, -- 'Ravi'
LENGTH(TRIM(TextVal)) AS Clean_Len -- Should be 4
FROM DATA;
This topic continues SQL's text functions — pulling out part of a string, and finding where one string sits inside another.
length characters starting at position start (SQL text positions start at 1, not 0).substring first occurs inside text, or 0 if it isn't found.SELECT SUBSTRING('Chemistry', 1, 4);
SELECT INSTR('Chemistry', 'ist');
SELECT CONCAT('Aisha', ' - ', 'Science');
SUBSTRING('Chemistry', 1, 4) returns 'Chem' — four characters, starting from position 1. INSTR('Chemistry', 'ist') returns 5 — 'ist' begins at the fifth character of 'Chemistry'. CONCAT('Aisha', ' - ', 'Science') returns 'Aisha - Science'.
Warning: SQL'sSUBSTRINGcounts positions starting at1, not0— unlike Python's zero-based indexing you already know.SUBSTRING('Chemistry', 1, 4)starts at the very first character, not the second.
This off-by-one difference from Python is worth deliberately noticing, precisely because it's the kind of detail that's easy to get wrong on an exam by instinctively applying Python's zero-based habit to SQL, where positions genuinely start counting from 1.
SUBSTRING(text, start, length) extracts part of a string, counting positions from 1; INSTR(text, substring) finds where a substring first occurs (0 if absent); CONCAT(...) joins strings together.
System Update: SQL Engine Ready.
Action: Run the blocks below to experiment with slicing strings.
Sometimes you only need a part of the text (e.g., the Area Code from a phone number).
| Function | Purpose | Example ('India') |
|---|---|---|
| LEFT(str, n) | Extracts n characters from the start. | LEFT('India', 2) → 'In' |
| RIGHT(str, n) | Extracts n characters from the end. | RIGHT('India', 2) → 'ia' |
| MID(str, pos, n) or SUBSTR() |
Extracts n characters starting from position pos. | MID('India', 2, 3) → 'ndi' |
/* ==================================================
SYSTEM SETUP
================================================== */
DROP TABLE IF EXISTS ITEMS;
CREATE TABLE ITEMS (Code VARCHAR(20));
INSERT INTO ITEMS VALUES ('NB-2024-X');
/* ==================================================
TASK: Slice the Code
Note: SQL Indexing starts at 1, not 0.
SUBSTR(String, Start_Pos, Length)
================================================== */
SELECT
Code,
LEFT(Code, 2) AS Category, -- 'NB'
RIGHT(Code, 1) AS Version, -- 'X'
SUBSTR(Code, 4, 4) AS Year -- Starts at 4th char, takes 4 chars -> '2024'
FROM ITEMS;
The INSTR function searches for a substring inside a main string and returns its position number.
INSTR(MainString, SearchString)
Example: INSTR('Hello', 'e') returns 2.
/* ==================================================
SYSTEM SETUP
================================================== */
DROP TABLE IF EXISTS USERS;
CREATE TABLE USERS (Email VARCHAR(30), Log VARCHAR(50));
INSERT INTO USERS VALUES ('student@school.com', 'Login Successful');
INSERT INTO USERS VALUES ('admin@gov.in', 'System Error: Disk Full');
/* ==================================================
TASK: Find Positions
================================================== */
SELECT
Email,
INSTR(Email, '@') AS At_Symbol_Location, -- Returns 8 for student@...
Log,
INSTR(Log, 'Error') AS Error_Location -- Returns 8 for 2nd row, 0 for 1st
FROM USERS;
This topic covers SQL's built-in functions for working with dates — getting the current date, and pulling out a specific part of one.
'Monday', 'Tuesday', ...).SELECT YEAR('2026-08-07');
SELECT DAYNAME('2026-08-07');
YEAR('2026-08-07') returns 2026, extracting only the year portion of that date. DAYNAME('2026-08-07') returns the name of whichever weekday that calendar date actually falls on.
Note:NOW()always returns the database server's current date and time at the moment the query runs — its result is never fixed, exactly like Python'srandommodule from Class 11, where the same call gives a different result depending on when (or, there, how) it's actually run.
Extracting just one part of a date — a year, a month, a weekday name — is exactly what makes it possible to filter or group records by a specific time period (every record from 2026, every Monday) without needing to compare full, exact date-and-time values.
NOW() returns the current date and time; YEAR(), MONTH(), and DAYNAME() extract a specific part from a given date value — useful for filtering or grouping data by a period rather than an exact date.
System Update: SQL Engine Ready.
Action: Run the blocks below. Note that Date functions can vary slightly between databases (MySQL vs SQLite), but we will focus on the Board Exam (MySQL) syntax.
In banking or attendance systems, we often need to record exactly when a transaction happened.
| Function | Return Value | Example Output |
|---|---|---|
| NOW() | Returns Date AND Time. | '2024-02-01 10:30:05' |
| CURDATE() or DATE() |
Returns ONLY the Date. | '2024-02-01' |
| SYSDATE() | System Date (Similar to NOW). | '2024-02-01 10:30:05' |
/* ==================================================
TASK: Check System Time
Note: We use standard syntax here.
================================================== */
SELECT
DATETIME('now') AS Current_Time_NOW, -- Exam uses NOW()
DATE('now') AS Current_Date_Only; -- Exam uses CURDATE()
If you have a date like '2024-12-25', you can extract specific parts using these functions.
/* ==================================================
SYSTEM SETUP
================================================== */
DROP TABLE IF EXISTS PROJECTS;
CREATE TABLE PROJECTS (ProjectName VARCHAR(20), DueDate DATE);
INSERT INTO PROJECTS VALUES ('Science Fair', '2024-08-15');
/* ==================================================
TASK: Extract Details
In Board Exams (MySQL), you would write:
SELECT MONTHNAME(DueDate), DAYNAME(DueDate) FROM PROJECTS;
(The code below simulates this logic for our viewer)
================================================== */
SELECT
ProjectName,
DueDate,
STRFTIME('%Y', DueDate) AS Year_Result, -- Returns 2024
STRFTIME('%m', DueDate) AS Month_Result, -- Returns 08
-- Simulating MONTHNAME for the viewer
CASE STRFTIME('%m', DueDate)
WHEN '08' THEN 'August'
END AS MonthName_Result
FROM PROJECTS;
Every function so far in this chapter computed a result from one row at a time. This closing topic covers functions that summarise an entire column across many rows into one single result.
NULL values; COUNT(\*) counts every row, NULL or not.SELECT SUM(Marks) FROM STUDENT;
SELECT AVG(Marks) FROM STUDENT;
SELECT COUNT(*) FROM STUDENT;
SUM(Marks) adds every student's Marks value into one total. AVG(Marks) computes the class average in one call. COUNT(*) returns how many rows the STUDENT table has in total, regardless of whether any column happens to be empty.
Note:COUNT(column)andCOUNT()can genuinely differ —COUNT(column)skips any row where that specific column isNULL, whileCOUNT()always counts every row.
These are called aggregate functions specifically because they collapse many rows down into one single summary value — the same conceptual job as Python's sum()/len()/max() on a list, or Pandas' identically-named methods from earlier in this course, just performed by the database itself before any result even reaches your program.
SUM(), AVG(), COUNT(), MAX(), and MIN() summarise an entire column across many rows into one value — COUNT(column) skips NULLs, while COUNT(*) always counts every row — the same aggregation idea already met in Python and Pandas, now performed directly by SQL.
System Update: SQL Engine Ready.
Action: Run this block to create a SALES table. We will use it to calculate Totals and Averages.
Aggregate functions (also called Multiple Row Functions) perform a calculation on a set of values and return a single value.
| Function | Purpose |
|---|---|
| SUM(col) | Adds up all values in the column. |
| AVG(col) | Calculates the Average (Mean). |
| MAX(col) | Finds the Highest value. |
| MIN(col) | Finds the Lowest value. |
| COUNT(col) | Counts the number of rows. |
/* ==================================================
SYSTEM SETUP (Sales Data)
================================================== */
DROP TABLE IF EXISTS SALES;
CREATE TABLE SALES (Item VARCHAR(20), Amount INT);
INSERT INTO SALES VALUES ('Laptop', 50000);
INSERT INTO SALES VALUES ('Mouse', 500);
INSERT INTO SALES VALUES ('Keyboard', 1500);
INSERT INTO SALES VALUES ('Monitor', 10000);
/* ==================================================
TASK: Calculate Aggregates
================================================== */
SELECT
SUM(Amount) AS Total_Revenue, -- 50000 + 500 + 1500 + 10000
AVG(Amount) AS Average_Price, -- Total / 4
MAX(Amount) AS Most_Expensive, -- 50000
MIN(Amount) AS Cheapest -- 500
FROM SALES;
This is the #1 trick question in exams.
What happens if a student is absent (NULL marks)?
/* ==================================================
SYSTEM SETUP (Data with NULL)
Ravi is absent (Marks is NULL)
================================================== */
DROP TABLE IF EXISTS EXAM;
CREATE TABLE EXAM (Name VARCHAR(20), Marks INT);
INSERT INTO EXAM VALUES ('Amit', 90);
INSERT INTO EXAM VALUES ('Sumit', 80);
INSERT INTO EXAM VALUES ('Ravi', NULL); -- Absent
INSERT INTO EXAM VALUES ('Pooja', 95);
/* ==================================================
TASK: Compare Counts
================================================== */
SELECT
COUNT(*) AS Total_Students, -- Returns 4 (Everyone)
COUNT(Marks) AS Students_Present -- Returns 3 (Ignores Ravi)
FROM EXAM;