Home / Computer Science / Class XII / Querying and SQL Functions
Querying and SQL Functions — CUET Computer Science hero
Class XII 💻 Computer Science Ch 14 of 20

Querying and SQL Functions

CUET unit: Querying and SQL Functions

📌 Snapshot

  • SQL functions, GROUP BY, HAVING, set operations and joins explained through CARSHOWROOM worked queries.
  • Single row functions (math, string, date) versus aggregate functions, with the exact outputs students must predict.
  • GROUP BY with HAVING, and why WHERE cannot filter groups.
  • UNION, INTERSECT, MINUS, Cartesian product and JOIN, including degree and cardinality of results.

📖 Detailed Notes

Written and reviewed by Rohit Singh, Computer Science & Commerce faculty at UniDrill (MCA, Osmania University · 6 years teaching). Based on NCERT Informatics Practices Class XII, Chapter 1.

How does a showroom owner get totals without counting by hand?

A car showroom has hundreds of sales. The owner wants the number of cars each customer bought, the average price of a model, the day of the week an employee joined, or the customer name next to each sale. Plain SELECT and WHERE cannot do all that. You need functions, which calculate on values, grouping, which summarises rows, and joins, which combine tables. This chapter adds all three to the SQL you learned in Class XI.

All the examples use a CARSHOWROOM database with four tables.

INVENTORY table.

CarId CarName Price Model YearManufacture FuelType
D001 Car1 582613.00 LXI 2017 Petrol
D002 Car1 673112.00 VXI 2018 Petrol
B001 Car2 567031.00 Sigma1.2 2019 Petrol
B002 Car2 647858.00 Delta1.2 2018 Petrol
E001 Car3 355205.00 5 STR STD 2017 CNG
E002 Car3 654914.00 CARE 2018 CNG
S001 Car4 514000.00 LXI 2017 Petrol
S002 Car4 614000.00 VXI 2018 Petrol

SALE table.

InvoiceNo CarId CustId SaleDate PaymentMode EmpID SalePrice
I00001 D001 C0001 2019-01-24 Credit Card E004 613247.00
I00002 S001 C0002 2018-12-12 Online E001 590321.00
I00003 S002 C0004 2019-01-25 Cheque E010 604000.00
I00004 D002 C0001 2018-10-15 Bank Finance E007 659982.00
I00005 E001 C0003 2018-12-20 Credit Card E002 369310.00
I00006 S002 C0002 2019-01-30 Bank Finance E007 620214.00

The CUSTOMER table holds CustId, CustName, CustAdd, Phone and Email (four customers, C0001 to C0004), and EMPLOYEE holds EmpID, EmpName, DOB, DOJ, Designation and Salary (seven employees). Both appear in the examples below when needed.

Two kinds of functions

Feature Single row (scalar) functions Aggregate (multiple row) functions
Operate on One row at a time A group of rows together
Result One result per row One result per group
Where used SELECT, WHERE, ORDER BY SELECT and HAVING (not WHERE)
Examples Math, string and date functions MAX, MIN, AVG, SUM, COUNT

A quick test. Ask "if my table had 100 rows, how many answers do I get?" A single row function gives 100; an aggregate with no GROUP BY gives 1.

Numeric functions

Function Purpose Example Output
POWER(X, Y) (or POW) X raised to the power Y SELECT POWER(2, 3); 8
ROUND(N, D) Round N to D decimal places; D = 0 gives an integer SELECT ROUND(2912.564, 1); 2912.6
ROUND(N) Nearest integer SELECT ROUND(283.2); 283
ROUND(N, -1) A negative D rounds to the left of the decimal point SELECT ROUND(342.9234, -1); 340
MOD(A, B) Remainder when A is divided by B SELECT MOD(21, 2); 1

Worked example: the EMI plan. The dealer adds 12 per cent tax to the price of car D001 (price 582613.00), then divides the amount into 10 EMIs that are multiples of 10000, with the leftover paid at once. Find the final price, the EMI and the leftover.

Code
SELECT CarId, Price + ROUND(Price*12/100, 1) AS FinalPrice
FROM INVENTORY
WHERE CarId = 'D001';
Step Calculation Result
1 Tax is $582613 \times 12 / 100 = 69913.56$, rounded to one decimal place 69913.6
2 Final price is $582613 + 69913.6$ 652526.6
3 Leftover is MOD(652526.6, 10000) 2526.6
4 Amount split into EMIs is $652526.6 - 2526.6 = 650000$ 650000
5 Each of the 10 EMIs is $650000 / 10$ 65000

The full query is SELECT CarId, FinalPrice, ROUND((FinalPrice - MOD(FinalPrice, 10000))/10, 0) AS EMI, MOD(FinalPrice, 10000) AS Remaining FROM INVENTORY;. A common wrong step is dividing the whole final price by 10, which gives 65252.66, not a multiple of 10000. MOD is what strips off the leftover first.

String functions

String functions take text and return text or a number. Positions start at 1 in SQL, not 0 as in Python.

Function Purpose Example Output
UCASE(s) or UPPER(s) Convert to capitals UPPER('Informatics Practices') INFORMATICS PRACTICES
LCASE(s) or LOWER(s) Convert to lower case LOWER('Informatics Practices') informatics practices
MID(s, pos, n), SUBSTR, SUBSTRING n characters from position pos; if n is left out, up to the end MID('Informatics', 3, 4) form
MID(s, pos) Without n: up to the end of the string MID('Informatics', 7) atics
LENGTH(s) Number of characters LENGTH('Informatics') 11
LEFT(s, n) First n characters LEFT('Computer', 4) Comp
RIGHT(s, n) Last n characters RIGHT('SCIENCE', 3) NCE
INSTR(s, sub) Position of the first occurrence of sub; 0 if absent INSTR('Informatics', 'ma') 6
LTRIM(s) Remove leading spaces LENGTH(LTRIM(' DELHI')) 5 (it was 7)
RTRIM(s) Remove trailing spaces LENGTH(RTRIM('PEN ')) 3 (it was 5)
TRIM(s) Remove spaces at both ends LENGTH(TRIM(' MADAM ')) 5 (it was 7)

Worked example: user name from an email. Display the part of every customer's email before the @ sign.

Code
SELECT LEFT(Email, INSTR(Email, '@') - 1)
FROM CUSTOMER;
Step Thinking For [email protected]
1 Find where @ sits INSTR returns 10
2 We want the characters before it, so 10 minus 1 9 characters
3 Take that many from the left amitsaha2

The result for the four customers is amitsaha2, rehnuma, charvi123 and gur_singh. The wrong step is LEFT(Email, INSTR(Email, '@')), which keeps the @ sign itself.

Another worked example: area code. If a four digit area code starts at position 3 of the phone number, SELECT MID(Phone, 3, 4) FROM CUSTOMER WHERE CustAdd LIKE '%Rohini%'; gives 1163 for the phone 6811635425: skip two digits, then take four. TRIM can also remove a named string from the ends, so TRIM('.com' FROM Email) turns [email protected] into amitsaha2@gmail.

Beyond the textbook. For the exam: LENGTH returns the number of characters. In reality: in MySQL, LENGTH() counts bytes, and CHAR_LENGTH() counts characters. For plain English letters the two agree, but a name written in Devanagari, for example, takes several bytes per character. Why it matters: when a length looks too big on non English text, use CHAR_LENGTH.

Date and time functions

Function Purpose Example Output
NOW() Current date and time SELECT NOW(); like 2019-07-11 19:41:17
DATE(x) Date part of a date and time DATE(NOW()) 2019-07-11
MONTH(d) Month number MONTH('2019-07-11') 7
MONTHNAME(d) Month name MONTHNAME('2003-11-28') November
YEAR(d) Year YEAR('2003-10-03') 2003
DAY(d) Day of the month DAY('2003-03-24') 24
DAYNAME(d) Weekday name DAYNAME('2019-07-11') Thursday

Worked example: employees who did not join on a Sunday.

Code
SELECT DAYNAME(DOJ), DAY(DOJ), MONTHNAME(DOJ), YEAR(DOJ)
FROM EMPLOYEE
WHERE DAYNAME(DOJ) != 'Sunday';
DAYNAME(DOJ) DAY(DOJ) MONTHNAME(DOJ) YEAR(DOJ)
Tuesday 12 December 2017
Friday 8 January 1999
Thursday 2 December 2010
Wednesday 23 October 2013

The EMPLOYEE table has seven rows; three joining dates (2016-06-05, 2012-07-01 and 2017-01-01) fall on a Sunday, so four rows survive. Here a single row function is used inside WHERE, something an aggregate function cannot do.

Aggregate functions

Aggregate functions summarise many rows into one value. Apart from COUNT(*), they skip NULL values.

Function Purpose Example on INVENTORY Output
MAX(col) Largest value SELECT MAX(Price) FROM INVENTORY; 673112.00
MIN(col) Smallest value SELECT MIN(Price) FROM INVENTORY; 355205.00
AVG(col) Average SELECT AVG(Price) FROM INVENTORY; 576091.625
SUM(col) Total SELECT SUM(Price) FROM INVENTORY; 4608733.00
COUNT(col) Number of non NULL values SELECT COUNT(DISTINCT Model) FROM INVENTORY; 6
COUNT(*) Number of rows, whatever they hold SELECT COUNT(*) FROM INVENTORY WHERE Model = 'VXI'; 2

For AVG, the filter WHERE Model = 'LXI' leaves two cars (582613 and 514000), so the average is $(582613 + 514000) / 2 = 548306.5$. COUNT(DISTINCT Model) is 6 because LXI and VXI each appear twice among 8 cars.

Pause and predict: a table MANAGER has four rows, and the MEMNAME column is AMIT, KAVREET, KAVITA and NULL. What do COUNT(MEMNAME) and COUNT(*) return?

Check your answer: COUNT(MEMNAME) is 3, because it skips the NULL. COUNT(*) is 4, because it counts rows, not values.

GROUP BY and HAVING

GROUP BY collects the rows that have the same value in a column into groups and applies an aggregate function to each group. HAVING then keeps only the groups that meet a condition.

Worked example: customers who bought more than one car.

Code
SELECT CustId, COUNT(*)
FROM SALE
GROUP BY CustId
HAVING COUNT(*) > 1;
Step What the DBMS does Result
1 Group the 6 sale rows by CustId C0001 has 2, C0002 has 2, C0003 has 1, C0004 has 1
2 Apply COUNT(*) to each group 2, 2, 1, 1
3 HAVING keeps counts above 1 C0001 and C0002
CustId COUNT(*)
C0001 2
C0002 2

Other useful forms from the same SALE table:

Query Result
SELECT PaymentMode, COUNT(*) FROM SALE GROUP BY PaymentMode ORDER BY PaymentMode; Bank Finance 2, Cheque 1, Credit Card 2, Online 1
SELECT EmpID, SUM(SalePrice) FROM SALE GROUP BY EmpID; E001 590321, E002 369310, E004 613247, E007 1280196, E010 604000
SELECT PaymentMode, SUM(SalePrice) FROM SALE GROUP BY PaymentMode HAVING SUM(SalePrice) > 1000000; Bank Finance 1280196

Where versus having. WHERE filters rows before grouping, and HAVING filters groups after grouping.

WHERE HAVING
Acts on Individual rows Groups made by GROUP BY
Can use aggregate function? No Yes
Runs Before grouping After grouping

The writing order is SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY. A rule that helps with SELECT: when you use GROUP BY, the plain columns in SELECT should be the grouping columns, and everything else should be an aggregate.

Pause and predict: why does SELECT CustId, COUNT(*) FROM SALE WHERE COUNT(*) > 1 GROUP BY CustId; fail?

Check your answer: WHERE is applied to single rows before any groups exist, so it cannot use an aggregate. The condition on the count belongs in HAVING.

Operations on relations

Three operations combine the rows of two tables: UNION, INTERSECT and MINUS (set difference). They are allowed only if both relations have the same number of attributes and corresponding attributes have the same domain. We use two class activity lists.

DANCE table.

SNo Name Class
1 Aastha 7A
2 Mahira 6A
3 Mohit 7B
4 Sanjay 7A

MUSIC table.

SNo Name Class
1 Mehak 8A
2 Mahira 6A
3 Lavanya 7A
4 Sanjay 7A
5 Abhay 8A
Operation Meaning Result for DANCE and MUSIC Rows
UNION Rows in either table; duplicates appear once Aastha, Mahira, Mohit, Sanjay, Mehak, Lavanya, Abhay 7
INTERSECT Rows common to both Mahira (2, 6A), Sanjay (4, 7A) 2
MINUS, DANCE minus MUSIC In DANCE but not in MUSIC Aastha, Mohit 2
MINUS, MUSIC minus DANCE In MUSIC but not in DANCE Mehak, Lavanya, Abhay 3

The order matters for MINUS. A minus B is not the same as B minus A. The union count follows the formula $|A \cup B| = |A| + |B| - |A \cap B|$, which gives $4 + 5 - 2 = 7$.

Beyond the textbook. For the exam: the three operations are UNION, INTERSECT and MINUS. In reality: MySQL has long supported UNION, but INTERSECT and EXCEPT (the standard SQL name for MINUS, which MySQL does not use) only arrived in recent versions from 8.0.31. Other systems such as Oracle write MINUS directly. Why it matters: the idea is the same everywhere, only the keyword changes.

Cartesian product pairs every row of the first table with every row of the second. The result has degree = sum of the degrees and cardinality = product of the cardinalities. For DANCE (degree 3, cardinality 4) and MUSIC (degree 3, cardinality 5), the product has degree $3 + 3 = 6$ and cardinality $4 \times 5 = 20$.

Using two tables in one query

Listing two tables in FROM separated by a comma applies a Cartesian product first. SELECT * FROM DANCE, MUSIC; therefore returns all 20 pairs. A condition in WHERE then keeps only the meaningful pairs.

Code
SELECT *
FROM DANCE D, MUSIC M
WHERE D.Name = M.Name;

The result keeps the 2 pairs where the names agree (Mahira and Sanjay). Here D and M are table aliases; once you alias a table, you must use the alias, not the original name, inside that query. Any column found in both tables, such as Name, needs the alias prefix to remove ambiguity.

JOIN pairs only the rows whose related columns match, which is what you almost always want. Usually one column is a primary key in one table and a foreign key in the other. Take UNIFORM(UCode, UName, UColor) with three rows (1 Shirt White, 2 Pant Grey, 3 Tie Blue) and COST(UCode, Size, Price) with four rows (1 L 580, 1 M 500, 2 L 890, 2 M 810).

Way of writing Query
Condition in WHERE SELECT * FROM UNIFORM U, COST C WHERE U.UCode = C.UCode;
Explicit JOIN SELECT * FROM UNIFORM U JOIN COST C ON U.UCode = C.UCode;
NATURAL JOIN SELECT * FROM UNIFORM NATURAL JOIN COST;

The first two give the same table with UCode shown twice. NATURAL JOIN shows it once.

UCode UName UColor Size Price
1 Shirt White L 580
1 Shirt White M 500
2 Pant Grey L 890
2 Pant Grey M 810

Worked example: size the results. UNIFORM has 3 rows and COST has 4 rows.

Query Thinking Rows
SELECT * FROM UNIFORM, COST; No condition, so every pair: $3 \times 4$ 12
Join on UCode Only matching codes. Shirt matches 2 cost rows, Pant matches 2 4

The Tie, with UCode 3, has no cost row, so it disappears from the join. The wrong answer is 12 for a join; that is the Cartesian product, with no matching condition applied.

A bigger join from CARSHOWROOM. To show each customer's name with the price they paid:

Code
SELECT CustName, SalePrice
FROM CUSTOMER C JOIN SALE S
ON C.CustId = S.CustId;

This returns 6 rows, one per sale. Add GROUP BY CustName with SUM(SalePrice) and you get totals per customer: AmitSaha 1273229, Rehnuma 1210535, CharviNayyar 369310 and Gurpreet 604000.

To join N tables on equality you need N minus 1 joins. Joining three tables needs two. With JOIN and ON you may also use operators other than equals.

Beyond the textbook. For the exam: NATURAL JOIN removes the repeated column. In reality: it matches on every column that has the same name in both tables, and if two tables later gain another column with the same name, the join silently changes. Explicit JOIN ... ON states exactly which columns you mean. Why it matters: in real projects, an explicit join condition is the safer habit.

Function sheet

Task Use
Round, power, remainder ROUND, POWER, MOD
Change case, cut, find, trim UPPER, LOWER, MID, LEFT, RIGHT, INSTR, TRIM
Parts of a date DAY, MONTH, YEAR, DAYNAME, MONTHNAME, NOW
Summaries MAX, MIN, AVG, SUM, COUNT
Per group GROUP BY
Filter groups HAVING
Combine rows of two tables UNION, INTERSECT, MINUS
Combine columns of two tables Cartesian product, JOIN, NATURAL JOIN

Exam traps

Trap Why it is tempting The truth
"COUNT(col) and COUNT(*) always agree" Both count COUNT(col) skips NULLs; COUNT(*) counts every row
"Use WHERE to filter a group total" WHERE is the filter you know Conditions on aggregates go in HAVING
"String positions start at 0" Python does In SQL, MID and INSTR positions start at 1
"A join of 3 and 4 row tables has 12 rows" 3 times 4 12 is the Cartesian product; a join returns only matching rows
"A minus B equals B minus A" Looks symmetric The order matters; A minus B keeps rows only in A
"Cartesian product has degree equal to the product" Cardinality multiplies Degrees add, cardinalities multiply
"ROUND(342.9234, -1) gives 342.9" Negative looks like an error A negative D rounds to tens: 340
"AVG counts NULL as 0" Missing looks like zero NULLs are ignored, so they do not lower the average

60-second revision

Topic Remember
Single row functions One output per row; usable in WHERE
Aggregate functions One output per group; skip NULL; not in WHERE
Math POWER(2,3) = 8; ROUND(2912.564,1) = 2912.6; MOD(21,2) = 1
Strings MID('Informatics',3,4) = form; INSTR is 1 based; TRIM both ends
Dates DAYNAME, MONTHNAME, YEAR, MONTH, DAY, NOW
GROUP BY One result per group; HAVING filters groups
Set operations Same degree and domains needed; UNION drops duplicates
Cartesian product Degree adds, cardinality multiplies
Joins Match key columns; N tables need N minus 1 joins

Where this chapter connects

This chapter builds on the SELECT, WHERE and ORDER BY of Introduction to Structured Query Language (SQL) and the keys of Database Concepts; the foreign keys from that chapter are exactly the columns you join on. The same grouping and aggregation ideas return in Data Handling Using Pandas - I, where a DataFrame replaces the table. The other Class XII SQL chapter is Structured Query Language (SQL).

🎯 Practice MCQs

First 3 questions free · create a free account to unlock the rest — answers & explanations included, no payment needed

Q1. Which of the following is an aggregate (multiple row) function?

▸ Show answer & explanation

Answer: C

AVG works on a set of rows and returns one value. UPPER, ROUND and MID are single row functions that return a result for each row.

Q2. What is the output of SELECT ROUND(123.2345, 2), ROUND(342.9234, -1);?

▸ Show answer & explanation

Answer: C

ROUND to 2 places gives 123.23. A negative second argument rounds to the left of the decimal point, so -1 rounds to the nearest ten, 340. Option A treats -1 as an error, B uses one decimal place, and D rounds incorrectly.

Q3. What is the output of SELECT MID('Informatics', 3, 4);?

▸ Show answer & explanation

Answer: B

The positions start at 1: I is 1, n is 2, f is 3. Four characters from position 3 give f, o, r, m, that is form. Option A starts from position 2, and option C from position 4.

🔒 12 more practice MCQs

Create a free account to unlock every MCQ in this chapter — answers and explanations included. No payment needed.

Already registered? Just log in and they'll all appear here.

📊 Previous-Year Questions

Practise with real CUET Computer Science previous-year papers — every question solved, with the correct answer and a step-by-step explanation.

View solved CUET PYQ papers →

Ready to drill Computer Science?

Unlock all MCQs, chapter tests, mocks & PYQs for ₹199/year.

Get UniDrill Pro