IT Learning HubIT Learning Hub
PRACTICE 02 · BTHT2

Querying Data with SQL

5 periodsDatabaseSQL Server

Objective: Use operators and functions to build query conditions; write SELECT to filter, sort, and group data; combine data from multiple tables with JOIN; use UNION/INTERSECT/EXCEPT; write nested queries with IN, ANY, ALL, EXISTS, NOT EXISTS.

01 · OPERATORS IN SQL

Operators

Operators are symbols or keywords used to perform calculations, comparisons, or combine conditions in a query.

The examples below assume the following table:

NhanVien

MaNVHoTenLuong
NV01Nguyễn An10000000
NV02Trần Bình15000000
NV03Lê Cường12000000

Arithmetic Operators

OperatorMeaning
+Addition
-Subtraction
*Multiplication
/Division
%Modulo (remainder)

Calculate salary after a 10% raise:

SELECT HoTen, Luong, Luong * 1.1 AS LuongMoi
FROM NhanVien;
HoTenLuongLuongMoi
Nguyễn An1000000011000000
Trần Bình1500000016500000
Lê Cường1200000013200000

Note: Arithmetic operators can be used directly inside SELECT to produce a computed value without saving a new column to the table.

Comparison Operators

OperatorMeaning
=Equal to
<> or !=Not equal to
>Greater than
<Less than
>=Greater than or equal to
<=Less than or equal to

Find employees earning over 10 million:

SELECT HoTen, Luong
FROM NhanVien
WHERE Luong > 10000000;

Find employees in department PB01:

SELECT *
FROM NhanVien
WHERE MaPB = 'PB01';

Logical Operators

OperatorMeaning
ANDAll conditions must be true
OROnly one condition needs to be true
NOTNegates a condition

AND - the employee must satisfy both conditions:

SELECT *
FROM NhanVien
WHERE Luong > 5000000
  AND MaPB = 'PB01';

OR - only one of the two conditions needs to be true:

SELECT *
FROM NhanVien
WHERE Luong > 15000000
   OR MaPB = 'PB01';

NOT - get employees not in PB01:

SELECT *
FROM NhanVien
WHERE NOT MaPB = 'PB01';

Special Operators

OperatorMeaning
LIKEMatches a string against a pattern
INValue is one of a given list
BETWEENValue falls within a range
IS NULLValue is undefined (empty)
IS NOT NULLValue is present (not empty)
ANYTrue for at least one value in the result set
ALLTrue for every value in the result set

LIKE is used to search by pattern, combined with two wildcard characters:

WildcardMeaning
%Represents any sequence of characters, including an empty one (0, 1, or many characters)
_Represents exactly one character

Starts with "Nguyễn" - Use % at the end:

SELECT HoTen
FROM NhanVien
WHERE HoTen LIKE N'Nguyễn%';

All of these would match: Nguyễn An, Nguyễn Bình, Nguyễn Văn Nam.

Ends with "An" - Use % at the start:

SELECT HoTen
FROM NhanVien
WHERE HoTen LIKE N'%An';

Contains "Văn" - Use % on both ends:

SELECT HoTen
FROM NhanVien
WHERE HoTen LIKE N'%Văn%';

_ replaces exactly one character - for example, finding a department code shaped like PB0 followed by exactly one digit:

SELECT *
FROM NhanVien
WHERE MaPB LIKE 'PB0_';

Matches PB01, PB02,... but not PB010, since the pattern PB0_ only accepts exactly 4 characters.

BETWEEN:

SELECT *
FROM NhanVien
WHERE Luong BETWEEN 10000000 AND 15000000;

IN:

SELECT *
FROM NhanVien
WHERE MaPB IN ('PB01', 'PB02');

02 · FUNCTIONS IN SQL

Functions in SQL

Functions process and transform data: numeric functions, string functions, date/time functions, and aggregate functions.
Important note: The original material presents some functions using generic SQL/MySQL syntax (NOW(), CURDATE(), LENGTH(), DATE_ADD(), CEIL()...). This practical course uses Microsoft SQL Server, so the functions below have been standardized to T-SQL - they run as-is, without copying the raw MySQL syntax.
MySQL / GenericT-SQL (SQL Server)
NOW()GETDATE()
CURDATE()CAST(GETDATE() AS DATE)
LENGTH()LEN()
CEIL()CEILING()
DATE_ADD(date, INTERVAL n unit)DATEADD(unit, n, date)
DATEDIFF(date1, date2) - number of daysDATEDIFF(DAY, date1, date2) - unit must be specified
GROUP_CONCAT(x)STRING_AGG(x, ', ') - a separator must be specified

Numeric Functions

FunctionPurpose
ABS()Absolute value
ROUND()Rounds a number
CEILING()Rounds up
FLOOR()Rounds down
SQRT()Square root
POWER()Exponent
SELECT
    ABS(-10) AS GiaTriTuyetDoi,
    ROUND(3.14159, 2) AS LamTron,
    SQRT(16) AS CanBacHai;

String Functions

FunctionPurpose
CONCAT()Concatenates strings
LEN()Counts characters
SUBSTRING()Extracts part of a string
TRIM()Strips leading/trailing whitespace
UPPER()Converts to uppercase
LOWER()Converts to lowercase
REPLACE()Replaces part of a string
SELECT
    HoTen,
    UPPER(HoTen) AS HoTenInHoa
FROM NhanVien;

Concatenate employee ID and name:

SELECT
    CONCAT(MaNV, ' - ', HoTen) AS ThongTinNhanVien
FROM NhanVien;

Date and Time Functions

FunctionPurpose
GETDATE()Returns the current date and time
YEAR()Extracts the year
MONTH()Extracts the month
DAY()Extracts the day
DATEADD()Adds/subtracts an interval to/from a date
DATEDIFF()Computes the difference between two dates

Get the year an employee was hired:

SELECT
    HoTen,
    YEAR(NgVL) AS NamVaoLam
FROM NhanVien;

Find how many days an employee has worked (T-SQL's DATEDIFF requires the unit DAY to be specified):

SELECT
    HoTen,
    DATEDIFF(DAY, NgVL, GETDATE()) AS SoNgayLamViec
FROM NhanVien;

Aggregate Functions

Unlike the 3 function groups above (which compute per row), aggregate functions compute over a set of many rows and return a single value - usually paired with GROUP BY in section 04.

FunctionPurpose
COUNT(*)Counts total rows (including rows with NULL)
COUNT(x)Counts rows where column x is not NULL
SUM(x)Sums column x
AVG(x)Averages column x
MAX(x)Largest value
MIN(x)Smallest value

Count employees and compute the sum/average salary:

SELECT
    COUNT(*) AS SoNhanVien,
    SUM(Luong) AS TongLuong,
    AVG(Luong) AS LuongTrungBinh,
    MAX(Luong) AS LuongCaoNhat,
    MIN(Luong) AS LuongThapNhat
FROM NhanVien;

03 · THE SELECT CLAUSE

SELECT

SELECT is one of the most important parts of SQL, used to retrieve data from one or more tables.

General Syntax

SELECT [DISTINCT] <ColumnList>
FROM <TableName>
[WHERE <Condition>]
[GROUP BY <ColumnList>]
[HAVING <GroupCondition>]
[ORDER BY <ColumnList> [ASC | DESC]];

Basic SELECT

Get all data:

SELECT *
FROM NhanVien;

Get only specific columns:

SELECT MaNV, HoTen, Luong
FROM NhanVien;

DISTINCT

Removes duplicate rows:

SELECT DISTINCT MaPB
FROM NhanVien;

Data PB01, PB01, PB02, PB02, PB03 ➜ result becomes just PB01, PB02, PB03.

WHERE

Used to filter rows based on a condition:

SELECT *
FROM NhanVien
WHERE Luong > 10000000
  AND MaPB = 'PB01';

ORDER BY

SELECT HoTen, Luong
FROM NhanVien
ORDER BY Luong DESC;

ASC - ascending, DESC - descending.

TOP

Example - get the most recently hired employee:

SELECT TOP 1 HoTen, NgVL
FROM NhanVien
ORDER BY NgVL DESC;

GROUP BY

Used to group rows sharing the same value. Example - number of employees in each department:

SELECT
    MaPB,
    COUNT(*) AS SoLuong
FROM NhanVien
GROUP BY MaPB;

HAVING

WHERE filters individual rows, while HAVING filters groups after GROUP BY. Example - only show salary levels shared by at least 3 employees:

SELECT
    Luong,
    COUNT(*) AS SoLuong
FROM NhanVien
GROUP BY Luong
HAVING COUNT(*) >= 3;
WHERE ↓ filter each row ↓ GROUP BY ↓ form groups ↓ HAVING ↓ filter groups

QUICK CHECK

Which clause is used to filter GROUPS of data after GROUP BY?

04 · JOIN OPERATIONS

JOIN

JOIN is used to combine data from two or more tables based on a related condition between them.
NhanVien
MaNV
HoTen
MaPB
PhongBan
MaPB
TenPB

NhanVien.MaPB = PhongBan.MaPB

INNER JOIN

Only returns rows that have matching data in both tables:

SELECT
    nv.HoTen,
    pb.TenPB
FROM NhanVien nv
INNER JOIN PhongBan pb
    ON nv.MaPB = pb.MaPB;

LEFT JOIN

Returns all data from the left table, even when there's no matching data in the right table:

SELECT
    nv.HoTen,
    pb.TenPB
FROM NhanVien nv
LEFT JOIN PhongBan pb
    ON nv.MaPB = pb.MaPB;
HoTenTenPB
Nguyễn AnPhòng KT
Trần BìnhPhòng KD
Lê CườngNULL

RIGHT JOIN

The opposite of LEFT JOIN: keeps all data from the right table:

SELECT
    nv.HoTen,
    pb.TenPB
FROM NhanVien nv
RIGHT JOIN PhongBan pb
    ON nv.MaPB = pb.MaPB;

FULL OUTER JOIN

Keeps data from both tables, whether or not there's a match:

SELECT
    nv.HoTen,
    pb.TenPB
FROM NhanVien nv
FULL OUTER JOIN PhongBan pb
    ON nv.MaPB = pb.MaPB;

CROSS JOIN

Produces a Cartesian product - if NhanVien has 5 rows and PhongBan has 3 rows, the result has 5 × 3 = 15 rows:

SELECT
    nv.HoTen,
    pb.TenPB
FROM NhanVien nv
CROSS JOIN PhongBan pb;

SELF JOIN

A table is used twice to express a relationship between rows within the same table - for example, employees and their managers:

SELECT
    nv.HoTen AS NhanVien,
    ql.HoTen AS QuanLy
FROM NhanVien nv
JOIN NhanVien ql
    ON nv.MaQL = ql.MaNV;

EQUI JOIN & Recommended Syntax

An EQUI JOIN compares related columns with =. Prefer the JOIN ... ON syntax:

FROM NhanVien nv
INNER JOIN PhongBan pb
    ON nv.MaPB = pb.MaPB

instead of putting the join condition in WHERE (still works, but not recommended):

FROM NhanVien nv, PhongBan pb
WHERE nv.MaPB = pb.MaPB;
SQL Server has no NATURAL JOIN: Some reference material (MySQL, PostgreSQL, Oracle) also has NATURAL JOIN - automatically joining on columns with matching names between two tables. T-SQL does not support this syntax - if you see it in other material, rewrite it with an explicit INNER JOIN ... ON condition as shown above.

05 · SET OPERATIONS

Set Operations

There are 3 main operations used to combine the results of multiple queries:

UNION INTERSECT EXCEPT

UNION

Takes all results and removes duplicate rows. Example - employees assigned to DA01 or DA02:

SELECT MaNV
FROM PhanCong
WHERE MaDA = 'DA01'

UNION

SELECT MaNV
FROM PhanCong
WHERE MaDA = 'DA02';

INTERSECT

Takes the intersection. Example - employees assigned to both DA01 and DA02:

SELECT MaNV
FROM PhanCong
WHERE MaDA = 'DA01'

INTERSECT

SELECT MaNV
FROM PhanCong
WHERE MaDA = 'DA02';

EXCEPT

Takes results from the first query that are not present in the second. Example - employees assigned to DA01 but not DA02:

SELECT MaNV
FROM PhanCong
WHERE MaDA = 'DA01'

EXCEPT

SELECT MaNV
FROM PhanCong
WHERE MaDA = 'DA02';
A UNION B ➜ A or B A INTERSECT B ➜ A and B A EXCEPT B ➜ A but not B

06 · NESTED QUERIES - SUBQUERY

Subquery

A Subquery is a query placed inside another query. The inner query runs to provide a result for the outer query.
SELECT TenSP
FROM SanPham
WHERE MaSP IN
(
    SELECT MaSP
    FROM HoaDon
);

Non-Correlated Subquery

An inner query that does not depend on the outer query. Example - find products sold in January 2024:

SELECT TenSP
FROM SanPham
WHERE MaSP IN
(
    SELECT MaSP
    FROM HoaDon
    WHERE MONTH(NgayBan) = 1
      AND YEAR(NgayBan) = 2024
);

IN / NOT IN

IN - checks whether a value is present in the subquery's result set:

SELECT TenSP
FROM SanPham
WHERE MaSP IN
(
    SELECT MaSP
    FROM HoaDon
);

NOT IN - find products that have never appeared on an invoice:

SELECT TenSP
FROM SanPham
WHERE MaSP NOT IN
(
    SELECT MaSP
    FROM HoaDon
);

ANY / ALL

ANY compares against at least one value in the subquery's result. Example - salary greater than any employee in PB01, PB02, or PB03:

SELECT HoTen, Luong
FROM NhanVien
WHERE Luong > ANY
(
    SELECT Luong
    FROM NhanVien
    WHERE MaPB IN ('PB01', 'PB02', 'PB03')
);

ALL requires the condition to hold against every value in the subquery. Example - products priced higher than every product in the Laptop category:

SELECT MaSP, TenSP, GiaBan
FROM SanPham
WHERE DanhMuc = 'Phu Kien'
  AND GiaBan > ALL
(
    SELECT GiaBan
    FROM SanPham
    WHERE DanhMuc = 'Laptop'
);
> ANY ➜ greater than at least one > ALL ➜ greater than all

EXISTS / NOT EXISTS

EXISTS checks whether a subquery returns at least one row. Example - employees with at least one order:

SELECT HoTen
FROM NhanVien nv
WHERE EXISTS
(
    SELECT *
    FROM DonHang dh
    WHERE dh.MaNV = nv.MaNV
);

Here, the subquery references the current row of the outer query (nv.MaNV) - this is called a Correlated Subquery.

NOT EXISTS - find employees with no orders at all:

SELECT HoTen
FROM NhanVien nv
WHERE NOT EXISTS
(
    SELECT *
    FROM DonHang dh
    WHERE dh.MaNV = nv.MaNV
);

07 · SUMMARY - WHICH TOOL TO USE?

Which Tool to Use?

A quick-reference table: knowing the syntax is one thing, but knowing when to use what is what matters.

TaskTool
Filter dataWHERE
Multiple conditionsAND, OR, NOT
Search by patternLIKE
Search within a listIN
Sort resultsORDER BY
Remove duplicatesDISTINCT
Group rowsGROUP BY
Filter groupsHAVING
Combine tablesJOIN
Combine query resultsUNION
Common partINTERSECT
Has A but not BEXCEPT
Compare against a result setANY, ALL
Check data existsEXISTS
Check data doesn't existNOT EXISTS

08 · PRACTICE EXERCISES

Comprehensive Practice

OFFICIAL ASSIGNMENT · BTTH2

Sales Management - Questions 1 ➜ 25

See the full assignment, attached files, and detailed answers (access code required) for BTTH2.

View exercise & answers ›