Beginner's Guide
Beginner's Guide
Collecting and storing data for analysis is a very human activity and we have been doing it
for thousands of years. In modern times, we have come up with the term data analysis
which is focused on part data discovery, data interpretation, and data communication. In
order to effectively work with huge amounts of data in an organized and efficient manner,
databases were invented.
These constraints are used to enforce certain rules or conditions that must be met
before data can be stored in a database. The purpose of integrity constraints is to
maintain the quality of data and prevent any errors or inconsistencies that may arise due
to incorrect or inconsistent data entry.
2. Domain Constraints: refer to the rules defined for the values that can be
stored for a certain attribute e.g. NOT NULL, UNIQUE, etc.
Although tables in general can have duplicate rows of data but a true relation
cannot have duplicate data.
The main data objects are termed entities/columns, with their details defined as
attributes. For example, a database column that stores employee names might have an
attribute that specifies the maximum length of the name, or an attribute that indicates
whether the column can contain null values. Some of these attributes are important and
are used to identify the entity, and different entities are related using relationships.
3. Derived attributes: These are the attributes that are not present in the whole
database but are derived using other attributes. For example, the average age of
users in a store.
KEYS
1 Akon 9876723452 17
2 Akon 9991165674 19
3 Bkon 7898756543 18
4 Ckon 8987867898 19
5 Dkon 9990080080 17
Super Key
Super Key is defined as a set of attributes within a table that can uniquely
identify each record within a table. In the table defined above super key would
include student_id , (student_id, name) , phone etc.
Confused? The first one is pretty simple as student_id is unique for every row of
data, hence it can be used to identify each row uniquely.
Next comes, (student_id, name) , now names of two students can be the same,
but their student_id can't be the same hence this combination can also be a key.
Similarly, the phone number for every student will be unique, hence
again, phone can also be a key. So they all are super keys.
Candidate Key
Candidate keys are defined as the minimal set of fields that can uniquely identify
each record in a table. It is an attribute or a set of attributes that can act as a
Primary Key for a table to uniquely identify each record in that table. There can
be more than one candidate key.
In our example, student_id and phone both are candidate keys for table Student.
A candidate key can never be NULL or empty. And its value should be
unique.
Primary Key
A primary key is a candidate key that is most appropriate to become the main key
for any table. It is a key that can uniquely identify each record in a table. It can be
any column or a group of multiple columns, and there can only be one primary
5
key in a table. The value cannot be repeated or null. It is a required field for
concatenating data tables and improving the efficiency of searching data.
Composite Key
Whenever a primary key consists of two or more attributes that uniquely identify
any record in a table, it is called a Composite key. But the attributes which
together form the Composite key are not a key independently or individually e.g.
(Student_id, Subject_id) .
Foreign Key
When it’s determined that a pair of tables have a relationship with each other, we
can typically establish the relationship by taking a copy of the primary key from
the first table and inserting it into the second table, where it becomes a foreign
key.
MySQL
The client program(s) are installed locally on the machine, but the server can be
installed anywhere, as long as clients can connect to it. Thus, DBMS provides
concurrent use of the system allowing efficient data retrieval, providing protection
and security to the databases and maintaining data consistency in the case of multiple
users.
#Creating a user and password, and Provide access to specific database ONLY
mysql> GRANT ALL ON sakila.* TO 'cbuser'@'localhost' IDENTIFIED BY 'cbpass';
#If you plan to make connections to the server from another host, substitute that host in
With SQL, statements define the necessary inputs and outputs, but the manner in which a
statement is executed is left to a component of the database engine known as
the optimizer. The optimizer’s job is to look at your SQL statements and, taking into
account how your tables are configured and what indexes are available, decide the most
efficient execution path (well, not always the most efficient). Most database engines will
allow you to influence the optimizer’s decisions by specifying optimizer hints, such as
suggesting that a particular index be used.
To communicate with databases, SQL has four sublanguages for tackling different jobs, and
these are mostly standard across database types
The TRUNCATE command removes all the records from a table. But this command
will not destroy the table's structure. When we use the TRUNCATE command on a
table its (auto-increment) primary key is also initialized. Following is its syntax,
DROP command completely removes a table from the database. This command
will also destroy the table structure and the data stored in it. Following is its syntax,
8
DROP TABLE table_name;
RENAME command is used to set a new name for any existing table. Following is the
syntax,
9
📌 Isn't DELETE the same as TRUNCATE ?
For e.g.: If you have a table with 10 rows and an auto_increment primary
key, and if you use the DELETE command to delete all the rows, it will delete
all the rows, but will not re-initialize the primary key, hence if you will insert
any row after using the DELETE command, the auto_increment primary key
will start from 11. But in the case of the TRUNCATE command, the primary
key is re-initialized, and it will again start from 1.
Command Description
Datatypes
CHAR(size) -- Fixed length string which can contain letters, numbers and special chara
cters. The size parameter sets the maximum string length, from 0 – 255 with a default
of 1.
VARCHAR(size) -- Variable length string similar to CHAR(), but with a maximum string l
ength range from 0 to 65535.
/*Text/Blob: Holds longer strings that don’t fit in a VARCHAR. Descriptions or free te
xt entered by survey respondents might be held in these fields*/
TEXT(size) -- Holds a string with a maximum length of 65535 bytes. Again, better to us
e VARCHAR().
BLOB(size) -- Holds Binary Large Objects (BLOBs) with a max length of 65535 bytes.
TINYBLOB -- Holds Binary Large Objects (BLOBs) with a max length of 255 bytes.
11
TINYTEXT -- Holds a string with a maximum length of 255 characters. Use VARCHAR() inst
ead, as it’s fetched much faster.
MEDIUMBLOB -- Holds Binary Large Objects (BLOBs) with a max length of 16,777,215 byte
s.
LONGBLOB -- Holds Binary Large Objects (BLOBs) with a max length of 4,294,967,295 byte
s.
ENUM(a, b, c, etc…) -- A string object that only has one value, which is chosen from a
list of values which you define, up to a maximum of 65535 values. If a value is added
which isn’t on this list, it’s replaced with a blank value instead.
SET(a, b, c, etc…) -- A string object that can have 0 or more values, which is chosen
from a list of values which you define, up to a maximum of 64 values.
CHAR vs VARCHAR
Value CHAR(4) Storage VARCHAR(4) Storage
‘‘ ‘‘ 4 bytes ‘‘ 1 byte
CHAR and VARCHAR are both character data types in SQL, but they have some key
differences:
2. Efficiency:
If you're dealing with strings that have a consistent length (e.g., country
codes or fixed-format codes), CHAR can be more efficient because the
storage size is fixed and the database doesn't need to spend extra effort in
handling the variable length.
12
the actual data used, potentially saving storage space.
Use CHAR when you have data with a consistent, known length, such as
codes, abbreviations, or fixed-format data. This can lead to faster retrieval
times and reduced storage overhead.
Use VARCHAR when you have data with varying lengths, or when you're
unsure about the maximum length. This can help save storage space and
better accommodate different data inputs.
BIT(size) -- A bit-value type with a default of 1. The allowed number of bits in a val
ue is set via the size parameter, which can hold values from 1 to 64.
BOOL -- Essentially a quick way of setting the column to TINYINT with a size of 1. 0 i
s considered false, whilst 1 is considered true.
FLOAT(p) -- A floating point number value. If the precision (p) parameter is between 0
to 24, then the data type is set to FLOAT(), whilst if it's from 25 to 53, the data ty
pe is set to DOUBLE(). This behaviour is to make the storage of values more efficient.
DOUBLE(size, d) -- A floating point number value where the total digits are set by the
size parameter, and the number of digits after the decimal point is set by the d param
eter.
DECIMAL(size, d) -- An exact fixed point number where the total number of digits is se
t by the size parameters, and the total number of digits after the decimal point is se
t by the d parameter.
TINYINT(size) -- A very small integer with a signed range of -128 to 127, and an unsig
ned range of 0 to 255. Here, the size parameter specifies the maximum allowed display
width, which is 255.
SMALLINT(size) -- A small integer with a signed range of -32768 to 32767, and an unsig
ned range from 0 to 65535. Here, the size parameter specifies the maximum allowed disp
lay width, which is 255.
13
BIGINT(size) -- A medium integer with a signed range of -9223372036854775808 to 922337
2036854775807, and an unsigned range from 0 to 18446744073709551615. Here, the size pa
rameter specifies the maximum allowed display width, which is 255.
FLOAT vs DOUBLE
FLOAT and DOUBLE are both floating-point data types in SQL, used to store
approximate numeric values with decimal points. They differ in terms of precision,
storage size, and range:
2. Efficiency:
Use FLOAT when you need to store approximate numeric values with
moderate precision, and storage space or performance is a concern. It's
suitable for most applications where slight inaccuracies are acceptable.
Use DOUBLE when you need to store approximate numeric values with higher
precision or a larger range. It's suitable for scientific or financial applications
where greater accuracy is required.
DATE -- A simple date in YYYY-MM–DD format, with a supported range from ‘1000-01-01’ t
o ‘9999-12-31’.
DATETIME(fsp) -- A date time in YYYY-MM-DD hh:mm:ss format, with a supported range fro
m ‘1000-01-01 00:00:00’ to ‘9999-12-31 23:59:59’. By adding DEFAULT and ON UPDATE to t
14
he column definition, it automatically sets to the current date/time.
DATETIME VS TIMESTAMP
DATETIME and TIMESTAMP are both data types in SQL used to store date and time
values. They have some differences in terms of storage format, range, and time
zone handling:
DATETIME : Stores date and time values as a combination of the date and
time, usually without time zone information. The typical range for DATETIME in
most database systems is from '1000-01-01 00:00:00' to '9999-12-31
23:59:59'.
TIMESTAMP: Stores date and time values as a single value, representing the
number of seconds elapsed since the Unix epoch ('1970-01-01 00:00:00
UTC'). The typical range for TIMESTAMP in most database systems is from
'1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.
DATETIME : Does not store time zone information and is not affected by time
zone settings. It represents the same point in time regardless of the time
zone.
TIMESTAMP : Stores date and time values in UTC, but it can be converted to
the local time zone when retrieved, based on the database or session time
zone settings.
3. Efficiency:
DATETIME: Can be less efficient in terms of storage, as it stores the date and
time separately. However, it can be easier to work with when time zone
conversion is not required.
15
4. When to use one over the other:
Use DATETIME when you need to store date and time values without
considering time zones, or when you want to store dates outside the
TIMESTAMP range. This is useful for applications where time zone conversion
Use TIMESTAMP when you need to store date and time values with time zone
awareness, or when you require efficient storage and automatic time zone
conversion. This is suitable for applications where time zone conversion is
important, such as when dealing with international dates and times.
NULL (Special)
In SQL, a Null represents a missing or unknown value; a Null does not represent
a zero, a character string of one or more blank spaces, or a “zero-length” character
string.
The major drawback of Nulls is their adverse effect on mathematical operations. Any
operation involving a Null evaluates to Null. This is logically reasonable—if a number
is unknown, then the result of the operation is necessarily unknown.
(25 * 3) + 4 = 79
(Null * 3) + 4 = Null
Constraints
NOT NULL (Domain Integrity)
The specified entity can’t be left blank/unknown
16
DEFAULT (Domain Integrity)
The specified entity will take the default value if it was left blank while creation.
--A better way is to name the constraint so that it provides usedful information
--when code raises exception
CREATE TABLE users2 (
username VARCHAR(20) NOT NULL,
age INT,
CONSTRAINT age_not_negative CHECK (age >= 0)
);
17
CRUD - Create, Read, Update, Delete
/*Create Tables*/
CREATE TABLE <table_name>
(<column_name1> <data_type1>, /*datatype - what kind of data will populate the col*/
<column_name2> <data_type2>);
/*Default behavior is to allow NULLs if not specified in a table. Let's define a table wit
h NOT NULL constraint*/
CREATE TABLE <table_name> (
id INT NOT NULL AUTO_INCREMENT,
<column_name1> VARCHAR(100) NOT NULL DEFAULT 'Unnamed',
<column_name2> INT NOT NULL,
PRIMARY KEY (id) );
A database can contain many related tables interlinked amongst each other through
relationships. The following shows a table called ‘customer’ that contains 9 columns
(fields) and multiple rows (records). Each row corresponds to one specific customer
whereas each column contains an attribute related to customer details.
18
/*Example*/
CREATE TABLE employee
(
employee_id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
address_id SMALLINT FOREIGN KEY REFERENCES address(id),
middle_name VARCHAR(255),
age INT NOT NULL,
pay_date DATE,
amount DECIMAL(8,2),
current_status VARCHAR(255) NOT NULL DEFAULT 'employed'
);
19
ADD CONSTRAINT positive_pprice CHECK (purchase_price >= 0);
🔸Querying in SQL
SELECT…FROM
used in conjunction with other keywords and clauses to find and view the information in
an almost limitless number of ways.
FROM is the second most important clause in the SELECT statement and is also
required. You use the FROM clause to specify the tables from which to draw the
columns you’ve listed in the SELECT clause
When you execute a SELECT statement, it usually retrieves one or more rows of
information—the exact number depends on how you construct the statement. These
rows are collectively known as a result set.
Use the DISTINCT keyword in your SELECT statement, and the result set will be free
and clear of all duplicate rows. DISTINCT is an optional keyword that evaluates the
values of all the columns as a single unit on a row-by-row basis and eliminates any
redundant rows it finds.
WHERE
clause can filter records/rows based on logical operators. The WHERE clause contains
a search condition that it uses as the filter. This search condition provides the
mechanism needed to select only the rows you need or exclude the ones you don’t
want. Your database system applies the search condition to each row in the logical table
defined by the FROM clause.
Standard numerical/string/date
col_name != 4 col_name = "abc"
operators = equal to <>, != not equal to
=, !=, < <=, >, >= payment_date>'2006-01-01' -- yyyy-
< less than > greater than <= less than
mm-dd
or equal to >= greater than or equal to
Character string can be any length but must have Gates, Matthews,
'_at%'’
“at” as the second and third letters Patterson
You can combine two or more conditions by using the AND and OR operators, and the
complete set of conditions you’ve combined to answer a given request constitutes a
single search condition.
SELECT
DISTINCT customer_id,
rental_id,
amount,
payment_date
FROM payment
WHERE customer_id IN (42,53,60,75)
OR amount>5;
SELECT
customer_id,
rental_id,
amount,
payment_date
FROM payment
WHERE customer_id<101
AND amount>5
AND payment_date>'2006-01-01'; -- yyyy-mm-dd
22
SELECT * FROM people WHERE HOUR(birthtime)
BETWEEN 12 AND 16;
The ESCAPE(\) option allows you to designate a single character string literal—known
as an escape character—to indicate how the database system should interpret a
percent sign or underscore character within a pattern string. Place the escape character
after the ESCAPE keyword and enclose it within single quotes, as you would any
character string literal. When the escape character precedes a wildcard character in a
pattern string, the database system interprets that wildcard character literally within the
pattern string.
To retrieve Null values from a value expression, we use the Null condition.
Note: A condition such as <ValueExpression> = Null is invalid because the value of the
value expression cannot be compared to something that is, by definition, unknown.
GROUP BY
used to specify how to group the data in our results and comes before HAVING and
ORDER BY clauses in our query. It works similarly to Pivot Tables in Excel.
📌 Think ‘dimensions’ vs ‘metrics’. Make sure all the dimensions are in our
GROUP BY.
Multiple columns can be specified at once using GROUP BY to create sub-groups in our
result set (similar to multiple row or column labels in a PivotTable!!).
TIP: Group by customer segment and add a time dimension to create cohort trends.
SELECT
replacement_cost,
COUNT DISTINCT(film_id) AS Number_of_films,
AVG(rental_rate) AS Avg_rental_rate,
MIN(rental_rate) AS Min_rental_rate,
MAX(rental_rate) AS Max_rental_rate
FROM film
GROUP BY replacement_cost;
WITH ROLLUP
the modifier used in SQL's GROUP BY clause to generate summary and subtotal rows for
grouped data, providing a quick way to analyze hierarchical or aggregated data. It is
particularly useful when you want to calculate subtotals and grand totals along with the
grouped data.
+--------+---------+-------------------+
| region | product | SUM(sales_amount) |
+--------+---------+-------------------+
| EAST | Mobile | 42 |
| EAST | IPads | 50 |
| EAST | NULL | 46 |
| WEST | Mobile | 60 |
| WEST | NULL | 60 |
| NULL | NULL | 50.66 |
+---------+--------+-------------------+
HAVING
can only be used with GROUP BY!! HAVING lets us specify the filtering logic the we
want to apply to our group-level aggregated metrics.
SELECT
customer_id,
COUNT(rental_id) AS total_rentals
FROM rental
GROUP BY customer_id
HAVING COUNT(rental_id)<15;
ORDER BY
specifies the order (ascending/descending) in which query results are displayed.
SELECT
title,
length,
rental_rate
FROM film
ORDER BY length DESC, title ASC;
Is any importance placed on the sequence of the columns in the ORDER BY clause?
The answer is “Yes!” The sequence is important because your database system will
evaluate the columns in the ORDER BY clause from left to right. Also, the importance of
the sequence grows in direct proportion to the number of columns you use.
25
The manner in which the ORDER BY clause sorts the information depends on the
collating sequence used by your database software. The collating sequence determines
the order of precedence for every character listed in the current language character set
specified by your operating system. For example, it identifies whether lowercase letters
will be sorted before uppercase letters, or whether a case will even matter.
LIMIT
LIMIT n tells the server to return the first n rows of a result set. LIMIT also has a two-
argument form that allows you to pick out any arbitrary section of rows from a result.
The arguments indicate how many rows to skip and how many to return. This means
that you can use LIMIT to do such things as skip two rows and return the next, thus
answering questions such as “what is the third-smallest or third-largest value?
+----+------+------------+-------+---------------+------+
| id | name | birth | color | foods | cats |
+----+------+------------+-------+---------------+------+
| 10 | Tony | 1960-05-01 | white | burrito,pizza | 0 |
+----+------+------------+-------+---------------+------+
Another alternative to limit the amount of data is to use Sampling technique. Sampling
can be accomplished by using a function on an ID field that has a random distribution of
digits at the beginning or end.
--If the ID field is an integer, mod can be used to find the last one, two, or more digits
and filter on the result:
WHERE mod(integer_order_id,100) = 6
--If the field is alphanumeric, you can use a right() function to find a certain number of
digits at the end
WHERE right(alphanum_order_id,1) = 'B'
26
Pivot Tables (COUNT..CASE)
allows us to process a series of IF/THEN logical operations in a specific order. When
you need to test the data in one column to determine how to handle data in another
column, you need to be able to say something like “If the value in column ‘a’ is ‘x’, then
return expression ‘y’, else return expression ‘z’.” The SQL Standard provides a handy
syntax to accomplish this: CASE
📌 Every CASE statement begins with CASE, ends with END, and contains at
least one WHEN/THEN pair.
SELECT
CONCAT(first_name,' ',last_name) AS name_customer,
CASE
WHEN store_id=1 AND active=1 THEN 'store 1 active'
We can use COUNT and CASE to replicate Excel’s ability to pivot to columns
SELECT
store_id,
COUNT(CASE WHEN active=1 THEN customer_id ELSE NULL END) AS 'active customer',
COUNT(CASE WHEN active=0 THEN customer_id ELSE NULL END) AS 'inactive customer'
FROM customer
GROUP BY store_id;
UNION removes duplicates from the result set, whereas UNION ALL retains all records,
whether duplicates or not. UNION ALL is faster since the database doesn’t have to go
over the data to find duplicates. It also ensures that every record ends up in the result
set.
SELECT order_date
,CAST('2020-05-01' as date) as order_date
,shirts_amount as shirts
,shoes_amount as shoes
,hats_amount as hats
FROM orders
28
UNION ALL
SELECT order_date
,CAST('2020-05-02' as date) as order_date
,shirts_amount as shirts
,shoes_amount as shoes
,hats_amount as hats
FROM orders
...
UNION combines tables by stacking new data from a different table below the existing
one. UNION deduplicates records and keeps only distinct values in the result set.
UNION ALL is used if we wish to keep all the records including duplicate records.
SELECT name,
IF(id IS NULL,'Unknown', id) AS 'id'
FROM taxpayer;
29
+---------+---------+
| name | id |
+---------+---------+
| bernina | 198-48 |
| bertha | Unknown |
| ben | Unknown |
| bill | 475-83 |
+---------+---------+
Detecting Duplicates
SELECT count(*)
FROM
(
SELECT column_a, column_b, column_c...
, count(*) as records
FROM...
GROUP BY 1,2,3...
) a
WHERE records > 1;
30
NUMERIC FUNCTIONS
CEIL -- Returns the closest whole number (integer) upwards from a given decimal point numb
er.
COUNT -- Returns the amount of records that are returned by a SELECT query.
FLOOR -- Returns the closest whole number (integer) downwards from a given decimal point n
umber.
MOD -- Returns the remainder of the given number divided by the other given number.
POW -- Returns the value of the given number raised to the power of the other given numbe
r.
ROUND -- Rounds the given number to the given amount of decimal places.
2 123456.789 123456.79
1 123456.789 123456.8
0 123456.789 123457
-1 123456.789 123460
-2 123456.789 123500
-3 123456.789 123000
SI 31
DATE FUNCTIONS
used with GROUP BY and aggregate functions like COUNT() and SUM() to perform
trend analysis. Some of the common ones are
SELECT
birthdate,
MONTHNAME(birthdate),
YEAR(birthdate)
FROM people;
DATEDIFF()
returns the number of days between two date values
SELECT
MIN(DATE (created_at)) AS week_start_date,
32
COUNT(CASE WHEN device_type='desktop'
THEN website_session_id
ELSE null END) AS dtop_sessions,
COUNT(CASE WHEN device_type='mobile'
THEN website_session_id
ELSE null END) AS mob_sessions
FROM website_sessions
WHERE
created_at BETWEEN '2012-04-15' AND '2012-06-9'
AND utm_source='gsearch'
AND utm_campaign='nonbrand'
GROUP BY WEEK(created_at);
STRING FUNCTIONS
Like most data types, strings can be compared for equality or inequality or relative
ordering. However, strings have some additional properties to consider:
Strings can be case sensitive (or not), which can affect the outcome of string
operations.
You can compare entire strings, or just parts of them by extracting substrings.
You can apply pattern-matching operations to look for strings that have a certain
structure.
CONCAT
joins two or more strings together
+-------------------------------------+
| title - author_fname - author_lname |
+-------------------------------------+
33
SUBSTRING
extracts user-provided characters from a string, index starts at 1
To return everything to the right or left of a given character,
use SUBSTRING_INDEX( str , c , n ) . It searches into a string str for the n -th
occurrence of the character c and returns everything to its left. If n is negative, the
search for c starts from the right and returns everything to the right of the character
SELECT name,
SUBSTRING_INDEX(name,'r',2),
SUBSTRING_INDEX(name,'i',-1)
FROM metal;
+----------+-----------------------------+------------------------------+
| name | SUBSTRING_INDEX(name,'r',2) | SUBSTRING_INDEX(name,'i',-1) |
+----------+-----------------------------+------------------------------+
| copper | copper | copper |
| gold | gold | gold |
| iron | iron | ron |
| lead | lead | lead |
| mercury | mercu | mercury |
| platinum | platinum | num |
| silver | silver | lver |
| tin | tin | n |
+----------+-----------------------------+------------------------------+
REPLACE
replaces all occurrences of a substring within a string, with a new substring
CHAR_LENGTH
return the length of a string (in characters)
34
LOCATE & POSITION
$ End of string
35
{m,n} m through n instances of preceding element
#Alternation example
SELECT name FROM metal WHERE name REGEXP '^[aeiou]|er$';
+--------+
| name |
+--------+
| copper |
| iron |
| silver |
+--------+
#Parentheses may be used to group alternations. For example, if you want to match strings
that consist entirely of digits or entirely of letters, you might try this pattern, using
an alternation
SELECT '0m' REGEXP '^[[:digit:]]+|[[:alpha:]]+$';
+-------------------------------------------+
| '0m' REGEXP '^[[:digit:]]+|[[:alpha:]]+$' |
+-------------------------------------------+
| 1 |
+-------------------------------------------+
36
A pattern consisting only of either SQL metacharacter matches all the values in the
table, not just the metacharacter itself:
37
🔸Advanced SQL
Joins
Database normalization is useful because it minimizes duplicate data in any single
table, and allows for data in the database to grow independently of each other. As a
trade-off, queries get slightly more complex since they have to be able to find data from
different parts of the database. In order to answer questions about an entity that has
data spanning multiple tables in a normalized database, we use JOINs.
The following are the common join types:
An INNER JOIN returns only those rows where the linking values match in both of the
tables or in result sets.
--or
A FULL OUTER JOIN or FULL JOIN asks your database system to return not only the
rows that match the criteria you specify but also the unmatched rows from either one or
both of the two sets you want to link
What’s the difference between LEFT JOIN and RIGHT JOIN? Remember that to specify
an INNER JOIN on two tables, you name the first table, include the JOIN keyword, and
then name the second table. When you begin building queries using OUTER JOIN, the
SQL Standard considers the first table you name as the one on the “left,” and the
second table as the one on the “right.” So, if you want all the rows from the first table
and any matching rows from the second table, you’ll use a LEFT OUTER JOIN or LEFT
JOIN. Conversely, if you want all the rows from the second table and any matching rows
from the first table, you’ll specify a RIGHT OUTER JOIN or RIGHT JOIN.
Multi-condition Joins:
SELECT
film.film_id,
[Link],
[Link] AS category_name
39
FROM film
INNER JOIN film category
ON film.film_id = film.category_id
INNER JOIN category
ON film_category.category_id = category.category_id
WHERE [Link] = 'horror' --This can be included in the join statements
ORDER BY film_id
SELECT
film.film_id,
[Link],
[Link] AS category_name
FROM film
INNER JOIN film category
ON film.film_id = film.category_id
INNER JOIN category
ON film_category.category_id = category.category_id
AND [Link] = 'horror'
ORDER BY film_id
#SELF JOIN
SELECT [Link], f_prnt.title prequel
FROM film f
INNER JOIN film f_prnt
ON f_prnt.film_id = f.prequel_film_id
WHERE f.prequel_film_id IS NOT NULL;
+------------------+
| title |
+------------------+
| BLOOD ARGONAUTS |
| TOWERS HURRICANE |
+------------------+
Subqueries
allows us to query another query. Simply put, a subquery is a SELECT expression that
you embed inside one of the clauses of a SELECT statement to form your final query
statement.
40
📌 Subqueries can be used in different parts of a SQL statement such as
SELECT, FROM, WHERE, and HAVING.
An alias must always be provided when using with FROM statement.
📌 When you use a subquery in the FROM clause, the result set returned from a
subquery is used as a temporary table. This table is referred to as a derived
table or materialized subquery.
--Example: Find the names of the employees who work in the same department as John.
SELECT emp_name
FROM employees
WHERE dept_id = (SELECT dept_id FROM employees WHERE emp_name = 'John');
--In this example, the subquery (SELECT dept_id FROM employees WHERE emp_name = 'Joh
n') returns multiple rows (all the departments where an employee named John works) wh
ich is used to compare with the department ID of each employee in the main query.
SELECT * FROM
(SELECT * FROM website_sessions
WHERE website_session_id <= 100) AS first_hundred;
--Alias must always be provided when using with FROM statement
--Example: Find the total sales for each employee in the company.
--In this example, the subquery (SELECT emp_id, SUM(sales_amount) as total_sales FROM
sales GROUP BY emp_id) returns a table with multiple rows (the total sales for each e
mployee) which is used as a table in the main query to join with the employees table.
SELECT [Link]
,[Link]
,[Link]
,(SELECT [Link]
FROM Customers
WHERE [Link] = [Link])
2. Row subquery - an embedded SELECT expression that returns more than one
column but no more than one row
3. Scalar subquery - an embedded SELECT expression that returns only one column
and no more than one row
--Example: Find the name of the employee who has the highest salary in the company.
SELECT emp_name
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);
--The subquery (SELECT MAX(salary) FROM employees) returns a single value (the maximu
m salary) which is used to compare with the salary of each employee in the main quer
y.
Temporary Tables
transient tables that exist only for the duration of the current session or transaction.
Temporary tables are useful for storing intermediate results, breaking down complex
operations into smaller steps.
Some APIs support persistent connections in a web environment. Use of these prevents
temporary tables from being dropped as you expect when your script ends, because the
web server keeps the connection open for reuse by other scripts. (The server may close
the connection eventually, but you have no control over when that happens.) This
means it can be prudent to issue the following statement prior to creating a temporary
table, just in case it’s still hanging around from the previous execution of the script: DROP
TABLE IF EXISTS tbl_name
Views
a virtual table based on the result set of an SQL statement. The tables that comprise the
view are known as base tables. A view contains rows and columns, just like a real table,
42
but there is no data associated with a view, it draws data from base tables rather than
storing any data on its own (this is why it’s called a virtual table). When you issue a
query against a view, your query is merged with the view definition to create a final
query to be executed.
For a view to be updatable, there must be a one-to-one relationship between the rows in
the view and the rows in the underlying table. There are also certain other constructs
that make a view non-updatable. To be more specific, a view is not updatable if it
contains any of the following:
DISTINCT
GROUP BY
HAVING
VIEW : A virtual table based on the result of a SELECT query. It does not
store data itself but instead represents a predefined query on one or more
existing tables. Views can simplify complex queries, provide data security by
restricting access to specific columns, and improve code maintainability.
43
TEMPORARY TABLE : A temporary, non-persistent table that exists only for the
duration of the current session or transaction. Temporary tables are useful
for storing intermediate results, breaking down complex operations into
smaller steps, or optimizing performance for certain tasks.
2. Data Storage:
VIEW : Does not store data; instead, it reflects the data stored in the
underlying tables. When you query a view, the database system executes
the underlying SELECT query and fetches the data from the base tables.
3. Efficiency:
Window Functions
Window functions perform calculations across a group of rows but produce a result FOR
EACH ROW , allowing you to create more advanced and flexible data analyses. They are
called "window functions" because they operate on a "window" of rows defined by an
OVER() clause.
Window functions can be used to calculate running totals, cumulative sums, moving
averages, rankings, percentiles, and other complex calculations that depend on the
context of the current row in relation to other rows in the result set.
The general structure of a window function is as follows:
<function>(<expression>) OVER (
[PARTITION BY <partition_expression>]
[ORDER BY <order_expression>]
[ROWS <frame_specification>]
)
44
1. : A window function, such as ROW_NUMBER(), RANK(),
<function>
3. PARTITION BY: Optional. It divides the result set into partitions to which the window
function is applied. If not specified, the function treats the whole result set as a
single partition.
4. ORDER BY: Optional. It orders the rows within each partition. The window function is
applied based on this order.
5. ROWS <frame_specification>: Optional. It defines the set of rows, or "frame", within the
partition that the window function operates on, relative to the current row.
SELECT
emp_no,
department,
salary,
MIN(salary) OVER(),
MAX(salary) OVER()
FROM employees;
SELECT
emp_no,
department,
salary,
AVG(salary) OVER(PARTITION BY department) AS dept_avg,
FROM employees;
SELECT
region,
product,
sales_amount,
SUM(sales_amount) OVER (PARTITION BY region ORDER BY product) as running_total
FROM sales_data;
1. RANK: Assigns a unique rank to each row within the result set, with the same
rank assigned to rows with equal values. When multiple rows share the same
rank, the next rank will be skipped. The syntax for RANK is:
2. DENSE_RANK: Assigns a unique rank to each row within the result set, with the
same rank assigned to rows with equal values. Unlike RANK , DENSE_RANK does not
skip any rank numbers when there are multiple rows with the same rank. The
syntax for DENSE_RANK is:
45
3. ROW_NUMBER : Assigns a unique number to each row within the result set,
regardless of the values in the columns. Even rows with equal values will receive
different row numbers. The syntax for ROW_NUMBER is:
Here's an example that demonstrates the difference between RANK , DENSE_RANK , and
ROW_NUMBER :
salesperson sales_amount
Alice 1000
Bob 2000
Carol 2000
Dave 3000
The following query will calculate the RANK , DENSE_RANK , and ROW_NUMBER for each
salesperson based on their sales_amount :
SELECT
salesperson,
sales_amount,
RANK() OVER (ORDER BY sales_amount DESC) as rank,
DENSE_RANK() OVER (ORDER BY sales_amount DESC) as dense_rank,
ROW_NUMBER() OVER (ORDER BY sales_amount DESC) as row_number
FROM sales_data;
As you can see, RANK skips the rank 3 (due to Bob and Carol sharing rank 2), while
DENSE_RANK does not skip any rank. ROW_NUMBER assigns a unique number to each row,
SELECT
emp_no,
department,
salary,
ROW_NUMBER() OVER(PARTITION BY department ORDER BY SALARY DESC) as dept_row_numbe
r,
RANK() OVER(PARTITION BY department ORDER BY SALARY DESC) as dept_salary_rank,
RANK() OVER(ORDER BY salary DESC) as overall_rank,
DENSE_RANK() OVER(ORDER BY salary DESC) as overall_dense_rank,
ROW_NUMBER() OVER(ORDER BY salary DESC) as overall_num
FROM employees ORDER BY overall_rank;
46
LEAD vs LAG
LEAD and LAG are window functions in SQL that allow you to access the value of a
row ahead or behind the current row within a result set, making it easier to compare
values between rows or calculate differences, growth rates, or other relative metrics.
1. LEAD: Retrieves the value of a given expression for the row that is N rows after
the current row, within the same result set. The syntax for LEAD is:
<expression> : The column or expression for which the value will be fetched.
<offset> : Optional. The number of rows ahead of the current row to fetch the
value from. Defaults to 1.
: Optional. The value to return if the lead value is not available (e.g.,
<default>
1. LAG: Retrieves the value of a given expression for the row that is N rows before
the current row, within the same result set. The syntax for LAG is:
<expression> : The column or expression for which the value will be fetched.
<offset> : Optional. The number of rows behind the current row to fetch the value
from. Defaults to 1.
: Optional. The value to return if the lag value is not available (e.g.,
<default>
Both LEAD and LAG require an ORDER BY clause within the OVER() clause to define the
order of rows within the result set.
Here's an example using LEAD and LAG to calculate the difference between the
current sales amount and the previous and next sales amounts:
SELECT
region,
product,
sales_amount,
sales_amount - LAG(sales_amount, 1) OVER (PARTITION BY region ORDER BY product) as
47
prev_difference,
LEAD(sales_amount, 1) OVER (PARTITION BY region ORDER BY product) - sales_amount a
s next_difference
FROM sales_data;
In this example, the LAG function calculates the difference between the current
sales_amount and the previous sales_amount within each region , while the LEAD
function calculates the difference between the current sales_amount and the next
sales_amount .
NTILE
NTILE() is a window function in SQL that is used to divide the result set into a
specified number of groups or "tiles" with roughly equal numbers of rows. It assigns
each row a tile number based on the ordering specified in the OVER() clause. NTILE()
is useful for scenarios such as dividing data into quartiles, percentiles, or other
equal-sized groups for further analysis.
SELECT
emp_no,
department,
salary,
NTILE(4) OVER(PARTITION BY department ORDER BY salary DESC) AS dept_salary_quartil
e,
NTILE(4) OVER(ORDER BY salary DESC) AS salary_quartile
FROM employees;
1. FIRST_VALUE : Retrieves the first value of the specified column in the window
frame. The syntax for FIRST_VALUE is:
FIRST_VALUE(<expression>) OVER (
[PARTITION BY <partition_expression>]
ORDER BY <order_expression>
[ROWS <frame_specification>]
)
1. LAST_VALUE : Retrieves the last value of the specified column in the window frame.
The syntax for LAST_VALUE is:
LAST_VALUE(<expression>) OVER (
[PARTITION BY <partition_expression>]
48
ORDER BY <order_expression>
[ROWS <frame_specification>]
)
1. NTH_VALUE : Retrieves the Nth value of the specified column in the window frame.
The syntax for NTH_VALUE is:
<expression> : The column or expression for which the value will be fetched.
<order_expression> : Orders the rows within each partition. The window function is
applied based on this order.
<N> : The position of the value to be retrieved within the window frame, where N
is a positive integer.
SELECT
region,
product,
sales_amount,
FIRST_VALUE(sales_amount) OVER (PARTITION BY region ORDER BY product) as first_val
ue,
LAST_VALUE(sales_amount) OVER (PARTITION BY region ORDER BY product ROWS BETWEEN U
NBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as last_value,
NTH_VALUE(sales_amount, 2) OVER (PARTITION BY region ORDER BY product) as nth_valu
e
FROM sales_data;
In this example, the FIRST_VALUE , LAST_VALUE , and NTH_VALUE functions retrieve the
first, last, and second sales amounts within each region as the rows are ordered by
product . Note the frame specification ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED
FOLLOWINGfor LAST_VALUE , which ensures that the entire window frame is considered
when retrieving the last value.
SQL variables hold single values. If you assign a value to a variable using a statement
that returns multiple rows, the value from the last row is used. Also, Variable names are
case sensitive
--+------+------+
--| @x | @X |
--+------+------+
--| 1 | NULL |
--+------+------+