0% found this document useful (0 votes)
9 views34 pages

Postgre SQL

This document provides a comprehensive guide on PostgreSQL database operations, including creating and dropping databases and tables, performing CRUD operations, and using data types and constraints. It also covers stored procedures, user-defined functions, and various SQL clauses and aggregate functions. Additionally, it includes examples for creating schemas and string functions, making it a valuable resource for users working with PostgreSQL.

Uploaded by

D Pavan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views34 pages

Postgre SQL

This document provides a comprehensive guide on PostgreSQL database operations, including creating and dropping databases and tables, performing CRUD operations, and using data types and constraints. It also covers stored procedures, user-defined functions, and various SQL clauses and aggregate functions. Additionally, it includes examples for creating schemas and string functions, making it a valuable resource for users working with PostgreSQL.

Uploaded by

D Pavan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

1​

#PostgreSQL#
Prepared by: Rohit S. Patil(Sr. Business Analyst)​
Mob: +91 9767548985​
Email: [email protected]

Tools: PgAdmin4 and SQL Shell[psql]

Create Database:

SYNTAX: CREATE DATABASE<DATABASE NAME>;

EX: CREATE DATABASE employee_db;

Drop Database:

SYNTAX: DROP DATABASE<DATABASE NAME>;

EX: DROP DATABASE employee_db;

❖​ Use \l or \list to check the list of databases in the SQL shell.​

❖​ Use \c <database_name> to connect to a database in the SQL shell.​

❖​ Run SELECT datname FROM pg_database; to check the database names in


pgAdmin4 and the SQL shell.​

❖​ Use \d <table_name> to view details about a table's columns, data types,


constraints, and indexes.​

❖​ Use \! cls to clear the SQL shell screen.​

❖​ Use \dv to describe views in the SQL shell.

Rohit S. Patil
2​

CRUD - CREATE, READ, UPDATE, DELETE​



Create a Table:

SYNTAX: ​
CREATE TABLE <TABLE NAME>(​
column1 datatype [constraints], ​
column2 datatype [constraints], ​
column3 datatype [constraints],​
—---------​
); ​

EX: CREATE TABLE students(​
student_id SERIAL PRIMARY KEY,​
first_name VARCHAR(50) NOT NULL,​
last_name VARCHAR(50) NOT NULL,​
birth_date DATE,​
email varchar(100) UNIQUE,​
phone_number VARCHAR(15),​
Enrollment_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP​
);

●​ SERIAL: Auto-incrementing integer (primary key).


●​ VARCHAR(n): String with a max length of n.
●​ NOT NULL: Ensures the column cannot be NULL.
●​ DATE: Stores date values.
●​ UNIQUE: Ensures no duplicate values in the column.
●​ TIMESTAMP DEFAULT CURRENT_TIMESTAMP: Automatically stores the current
date and time.

Adding data into a table:

SYNTAX: INSERT INTO <Table Name> (Column1, Column2, Column3, ……)​


​ VALUES(Value1, Value2, Value3,…..);

EX: INSERT INTO students(first_name, last_name, birth_date, email, phone_number)​


VALUES​
('Alice', 'Smith', '1999-10-20', '[email protected]', '987-654-3210'), ​
('Bob', 'Johnson', '2001-03-12', '[email protected]', '456-789-0123');

Reading data into a table:

SYNTAX: SELECT * FROM <table_name>;​

Rohit S. Patil
3​

SELECT <column_name> FROM <table_name>;

EX: SELECT * FROM students; ​


SELECT first_name, last_name, email FROM students;

Update/Modify data into a table:

SYNTAX: UPDATE <Table_name>​


SET Column1 = Value1, ​
Column2 = Value2, ……..​
WHERE Conditions;

EX: UPDATE students​


SET email = ‘[email protected]’, phone_number = ‘+919767548985’​
WHERE student_id=1; ​

DELETE data into a table:

SYNTAX: DELETE FROM <Table_Name>​


WHERE conditions;

Ex: DELETE FROM students​


WHERE student_id = 1;

DELETE a table:

SYNTAX: DROP TABLE <Table_name>

EX: DROP TABLE students;

DATA TYPES and CONSTRAINTS:

PostgreSQL data types can be categorized into:​


✅ Numeric​
✅ Character (String)​
✅ Date & Time​
✅ Boolean​
✅ JSON, Array, and Special Types

Rohit S. Patil
4​

Rohit S. Patil
5​

CONSTRAINTS:

1️⃣ Primary Key (PRIMARY KEY)


●​ Ensures unique and non-null values.
●​ Used to identify each row uniquely.

2️⃣ Unique (UNIQUE)

●​ Ensures that values in a column are unique.

3️⃣ Not Null (NOT NULL)

●​ Ensures that a column cannot store NULL values.

4️⃣ Check (CHECK)

●​ Ensures values meet a condition.

5️⃣ Default (DEFAULT)

●​ Assigns a default value if no value is provided.

Rohit S. Patil
6​

6️⃣ Foreign Key (FOREIGN KEY)

●​ Creates a link between two tables.

7️⃣ Auto-Increment (SERIAL & BIGSERIAL)

●​ Automatically generates a unique value.

#CREATE THE EMPLOYEE TABLE

CREATE TABLE Employee (


Emp_id SERIAL PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
Email VARCHAR(100) UNIQUE NOT NULL,
Phone VARCHAR(15) UNIQUE NOT NULL,
Hire_date DATE NOT NULL DEFAULT CURRENT_DATE,
Designation VARCHAR(100) NOT NULL,
Salary DECIMAL(10,2) NOT NULL DEFAULT 30000,
Dept VARCHAR(100) NOT NULL
);

#Inserting Data Into Table: (Provided Constraints)

INSERT INTO employee (emp_id, name, email, phone, hire_date, designation, salary,
dept)​
VALUES (1, 'Rohit Patil', '[email protected]', '9767548985', '2023-07-24', 'Sr.
Business Analyst', 60000, 'Business Analyst');

INSERT 0 1

INSERT INTO employee (name, email, phone, hire_date, designation, salary, dept)​
VALUES ('Priya Singh, '[email protected]', '9875485689', '2023-01-24', 'Software
Developer', 70000, 'Software Development');

Error: Key (emp_id)=(1) already exists.duplicate key value violates unique constraint
"employee_pkey"

Rohit S. Patil
7​

Solution To Resolve Error:

Open SqlShell[psql] - Connect to the Database and Describe the Table using \d employee; ​

Copy - nextval(‘employee_emp_id_seq’)

Query - SELECT SETVAL('employee_emp_id_seq', 1); - SET VAL - 1

SELECT CURRVAL('employee_emp_id_seq'); - CURR VAL - 1

Now Execute the Query:

INSERT INTO employee (name, email, phone, hire_date, designation, salary, dept)​
VALUES ('Priya Singh, '[email protected]', '9875485689', '2023-01-24', 'Software
Developer', 70000, 'Software Development');

Stored Routine:

1.​ Stored Procedure:

Ex: 1. CREATE OR REPLACE PROCEDURE add_employee(


IN p_name VARCHAR(100),
IN p_email VARCHAR(100),
IN p_phone VARCHAR(15),
IN p_designation VARCHAR(100),
IN p_dept VARCHAR(100),
IN p_salary DECIMAL(10,2) DEFAULT 30000,​
IN p_hire_date DATE DEFAULT CURRENT_DATE
)
LANGUAGE plpgsql
AS $$
BEGIN

Rohit S. Patil
8​

​ ​ INSERT INTO employee(name, email, phone, hire_date, designation, salary,


dept)
​ ​ VALUES (p_name, p_email, p_phone, p_hire_date, p_designation,
p_salary, p_dept);
END;
$$;

CREATE OR REPLACE PROCEDURE add_employee(...): Creates a stored procedure named


add_employee.
IN p_name, p_email, ...: Input parameters to accept employee details.
DEFAULT 30000: Ensures salary is 30,000 if not provided.
DEFAULT DATE: Ensures Current Date if not provided.
LANGUAGE plpgsql: Specifies that the procedure uses PL/pgSQL.
BEGIN ... END;: Contains the logic to insert employee data.

How to Execute the Procedure:

If you want to use the default values:


CALL add_employee('Ram Krishna','[email protected]', '9876432322',' Manager',
'Production');

If you want to provide a custom hire date and salary:​


CALL add_employee('Rohit Patil', '[email protected]', '9767548985', 'Sr. Business
Analyst', 'Business Analyst', '2023-07-24', 60000);

Ex: 2. CREATE OR REPLACE PROCEDURE update_emp_salary(


IN p_emp_id INT,
IN p_salary DECIMAL(10,2)
)
Language plpgsql
AS $$
BEGIN
UPDATE employee
​ SET Salary = p_salary
​ WHERE emp_id = p_emp_id;
END;
$$;

Rohit S. Patil
9​

How to Execute the Procedure:


CALL update_emp_salary( 2, 90000);

Ex: 3. CREATE OR REPLACE PROCEDURE update_employee(


IN p_emp_id INT,
IN p_name VARCHAR(100),
IN p_email VARCHAR(100),
IN p_phone VARCHAR(15),
IN p_designation VARCHAR(100),
IN p_dept VARCHAR(100),
IN p_salary DECIMAL(10,2) DEFAULT 30000,
IN p_hire_date DATE DEFAULT CURRENT_DATE
)
LANGUAGE plpgsql
AS $$
BEGIN
​ ​ UPDATE employee
​ ​ SET
​ ​ name = COALESCE(p_name, name),
​ ​ email = COALESCE(p_email, email),
​ ​ phone = COALESCE(p_phone, phone),
​ ​ hire_date = COALESCE(p_hire_date, hire_date),
​ ​ designation = COALESCE(p_designation, designation),
​ ​ salary = COALESCE(p_salary, salary),
​ ​ dept = COALESCE(p_dept, dept)
​ WHERE emp_id = p_emp_id;
​ ​ IF NOT FOUND THEN
​ ​ RAISE EXCEPTION 'No employee found with emp_id = %', p_emp_id;
​ ​ END IF;

END;
$$;

How to Execute the Procedure:

1. Update Only the Salary


CALL update_employee(1, NULL, NULL, NULL, NULL, NULL, 75000, NULL);

Rohit S. Patil
10​

2. Update Name & Department​


CALL update_employee(2, ‘Virat Kohli’, NULL, NULL, NULL, 'IT', NULL, NULL);

2. Update Multiple Fields


CALL update_employee(3, 'Alice Smith', '[email protected]', '9876543210', 'Project
Manager', 'Management', 85000, '2024-10-01');

●​ Throws an error if the emp_id does not exist.

2.​ User-Defined Function: ​



SYNTAX: CREATE OR REPLACE FUNCTION <FUNCTION NAME>(Input Parameter) ​
​ ​ RETURNS <RETURN TYPE> AS $$​
​ ​ BEGIN

​ ​ ​ ​ —--Function Logic—--​
​ ​ RETURN VALUE;​
​ ​ ​ END;​
​ ​ $$ LANGUAGE plpgsql;

EX: 1. ​
CREATE OR REPLACE FUNCTION calculate_bonus(emp_salary NUMERIC,
emp_experience INT)
RETURNS NUMERIC AS $$
BEGIN

--If Experience is greater than 10 Years, give a 20% Bonus

IF emp_experience > 10 THEN


RETURN emp_salary * 0.20;

---If Experience is Between 5 and 10 Years, give 10% Bonus


ELSIF emp_experience BETWEEN 5 and 10 THEN
RETURN emp_salary * 0.10;

--- Otherwise give 5% Bonus


ELSE
RETURN emp_salary * 0.05;

Rohit S. Patil
11​

END IF;
END;
$$ LANGUAGE plpgsql;


Function Name: calculate_bonus
Input Parameters:
emp_salary NUMERIC → Employee's salary
emp_experience INT → Employee's years of experience
Return Type: NUMERIC (returns the calculated bonus)
Logic Inside the Function:
If the employee has more than 10 years of experience, they receive 20% of their salary as
a bonus.
If the experience is between 5 and 10 years, they receive 10% of their salary as a bonus.
If the experience is less than 5 years, they receive 5% of their salary as a bonus.
Return Statement: Based on the conditions, the function returns the appropriate bonus
amount.

Calling the Function​


​ SELECT calculate_bonus(50000, 12); -- Employee with 12 years of experience

SELECT emp_id, emp_name, emp_salary, emp_experience,


​ calculate_bonus(emp_salary, emp_experience) AS bonus
FROM Employee; — If you have an employee table.

EX: 2. ​
CREATE OR REPLACE FUNCTION get_grade(score NUMERIC)
RETURNS TEXT AS $$
BEGIN
​ IF score>=90 THEN
​ RETURN 'A';
​ ELSIF score>=80 THEN
​ RETURN 'B';
​ ELSIF score>=70 THEN
​ RETURN 'C';
​ ELSIF score>=60 THEN
​ RETURN 'D';
​ ELSE
​ RETURN 'F';

Rohit S. Patil
12​

END IF;
END;
$$ LANGUAGE plpgsql

Calling the Function​


​ select get_grade(90);

CLAUSES:

1.​ WHERE:
○​ SELECT * FROM employee WHERE emp_id = 5;
○​ SELECT * FROM employee WHERE dept = ‘HR’
2.​ Relational Operator: < Less Than, > Greater Than, <= Less Than Equal To, >= Greater
Than Equal To, = Equal To, != Not Equal To
○​ SELECT * FROM employee WHERE dept= ‘BA’ OR fname= ‘Rohit’;
—-----Atleast one Condition should be True
○​ SELECT * FROM employee WHERE dept = ‘HR’ AND Salary >= 40000;
—---- Both Condition Should be True
3.​ IN Operator:
○​ SELECT * FROM employee WHERE dept IN(‘IT’, ‘HR’, ‘BA’);
4.​ NOT IN Operator
○​ SELECT * FROM employee WHERE dept NOT IN(‘IT’, ‘HR’, ‘BA’);
5.​ BETWEEN
○​ SELECT * FROM employee WHERE salary BETWEEN 40000 AND 60000;
6.​ DISTINCT
○​ SELECT DISTINCT dept FROM employee; — Only Distinct Values
7.​ ORDER BY: Ascending or Descending Order
○​ SELECT * FROM employee ORDER BY emp_id;
○​ SELECT * FROM employee ORDER BY emp_id DESC;
8.​ LIMIT:
○​ SELECT * FROM employee LIMIT 3; —-Starting 3 Rows Only
9.​ LIKE:
○​ SELECT * FROM employee WHERE fname LIKE ‘%A’; — a should be in the
end of fname
○​ SELECT * FROM employee WHERE fname LIKE ‘A%’; — a should be in the
First of fname
○​ SELECT * FROM employee WHERE dept LIKE ‘--’; — Two characters of Dept
Value

Rohit S. Patil
13​

Aggregate Functions: - COUNT, AVG, SUM, MIN, MAX

★​ Find the total Number of Employees:


○​ SELECT COUNT(emp_id) FROM employee;
★​ Find the total Salary of Employees:
○​ SELECT SUM(salary) FROM employee;
★​ Find the Average Salary of Employees:
○​ SELECT AVG(Salary) FROM employee;
★​ Find the Minimum Salary of Employees:
○​ SELECT MIN(salary) FROM employee;
★​ Find the Maximum Salary of Employees:
○​ SELECT MAX(salary) FROM employee;

GROUP BY Functions: -

★​ Find the Number of Employees in each department


○​ SELECT dept, COUNT(emp_id) FROM employee GROUP BY dept;
★​ Find the Total employee's salary in each department
○​ SELECT dept, SUM(salary) FROM employee GROUP BY dept;

CREATING SCHEMA: -

Syntax: CREATE SCHEMA schema_name; ​


Ex. CREATE SCHEMA company;

Creating a Table Inside a Schema:


CREATE TABLE company. students (
student_id SERIAL PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
birth_date DATE NOT NULL,
gender VARCHAR(10),
class VARCHAR(20),
);

Move the Table to the New Schema:


Syntax: ALTER TABLE old_schema.table_name SET SCHEMA new_schema;
Ex: ALTER TABLE public.employee SET SCHEMA company;

STRING FUNCTIONS: CONCAT, CONCAT_WS

Rohit S. Patil
14​


CONCAT:
●​ SELECT CONCAT(‘Hello’, ‘World’); - HelloWorld
●​ SELECT CONCAT(fname, lname) AS fullname FROM employee; - Rohitpatil
●​ SELECT emp_id CONCAT(fname,lname) AS fullname, dept FROM employee; - 1,
Rohitpatil, IT
●​ SELECT emp_id CONCAT(fname, ‘ ’, lname) AS fullname, dept FROM employee; - 1,
Rohit patil, IT


CONCAT_WS(With Separator):

●​ SELECT CONCAT_WS(‘:’ ‘One’, ‘Two’, ‘Three’); - ONE:TWO:THREE


●​ SELECT CONCAT_WS(‘-’ ‘One’, ‘Two’, ‘Three’); - ONE-TWO-THREE
●​ SELECT emp_id CONCAT_WS(‘ ’, fname, lname) AS fullname, dept, salary
FROM employee; - 1, Rohit Patil, IT, 25k

SUBSTRING FUNCTIONS:

SUBSTR
●​ SELECT SUBSTR(‘Hello Buddy’, 1, 6); - Hello
●​ SELECT SUBSTR(‘Hello Buddy!’, 7, 12); - Buddy!
​ REPLACE REPLACE(str, from_str, to_str);
●​ SELECT REPLACE(‘Hey Buddy’, ‘Hey’, ‘Hello’); - Hello Buddy
●​ SELECT REPLACE(dept, 'Software Development', 'Tech') AS updated_dept
FROM company.employee;
​ REVERSE
●​ SELECT REVERSE(fname) FROM employee; - tihoR
LENGTH
●​ SELECT LENGTH(fname) FROM employee;
●​ SELECT * FROM employee WHERE LENGTH(fname) >5;
​ UPPER & LOWER:
●​ SELECT UPPER(fname) FROM employee; - ROHIT
●​ SELECT LOWER(fname) FROM employee; - rohit
​ LEFT & RIGHT:
●​ SELECT LEFT(‘Hello World’, 4); - Hell
●​ SELECT RIGHT(‘Hello World’, 5); - World
​ TRIM: Function Inside Function
●​ SELECT LENGTH(‘ Alright ’); - Length: 14
●​ SELECT LENGTH(TRIM(‘ Alright ’)); - Length: 7
​ POSITION

Rohit S. Patil
15​

●​ SELECT POSITION('HI' IN 'ROHIT'); Position: 3

ALTERING TABLES

●​ ADD
■​ Ex: ALTER TABLE Employee
ADD column age INT;

●​ REMOVE
■​ Ex: ALTER TABLE Employee
DROP column age;
●​ RENAME - Column Name
■​ EX: ALTER TABLE Employee
RENAME name to full_name

●​ RENAME - Table Name


■​ Ex: ALTER TABLE employee
RENAME TO people;

Modification of Column Ex: Changing Datatype or Adding Default Value

●​ SET DATA TYPE:


■​ ALTER TABLE people
ALTER COLUMN full_name
SET DATA TYPE VARCHAR(150);

●​ SET DEFAULT:
■​ ALTER TABLE people
ALTER COLUMN dept
SET DEFAULT 'BusinessAnalyst';

●​ DROP DEFAULT:
■​ ALTER TABLE people
ALTER COLUMN dept DROP DEFAULT;

Rohit S. Patil
16​

●​ SET NOT NULL:


■​ ALTER TABLE people
ALTER COLUMN full_name
SET NOT NULL;

●​ DROP NOT NULL:


■​ ALTER TABLE people
ALTER COLUMN full_name
DROP NOT NULL;

CHECK CONSTRAINTS:

​ Ex: CREATE TABLE contacts(


name varchar(100),
mob varchar(15) UNIQUE
CHECK (LENGTH(mob)>=10)
);

INSERT INTO contacts(name,mob)


VALUES('Rohit',9767548985);

SELECT * FROM contacts; – Rohit, 9767548985

INSERT INTO contacts(name,mob)


VALUES(Raj, 880022550); –ERROR: Failing row contains (Raj, 880022550).new row
for relation "contacts" violates check constraint "contacts_mob_check"

DROP CONSTRAINTS:

​ Ex: ALTER TABLE contacts


​ DROP constraints Contact_mob_check;

​ INSERT INTO contacts(name,mob)


VALUES(Yash, 1245);

SELECT * FROM contacts; – Yash, 1245

Rohit S. Patil
17​

CASE:
​ Ex. SELECT fname, salary,
​ CASE
​ WHEN salary>=5000 THEN ‘HIGH’​
​ WHEN salary BETWEEN 48000 AND 50000 THEN ‘MID’
​ ELSE ‘LOW’
END AS sal_category FROM employee;​

Ex. SELECT fname, salary,


​ CASE
​ WHEN salary>0 THEN ROUND(salary*.10)
​ END AS bonus FROM employee;

RELATIONSHIP: One To One, One To Many, Many To Many

1.​ One To One:


​ ​ Ex. Each record in Table A is linked to only one record in Table B.

CREATE TABLE person (


​ id SERIAL PRIMARY KEY,
​ name VARCHAR(100)
);

CREATE TABLE passport (


​ id SERIAL PRIMARY KEY,
​ person_id INT UNIQUE, ​
passport_number VARCHAR(50) UNIQUE NOT NULL,
FOREIGN KEY (person_id) REFERENCES person(id)
);

INSERT INTO person (name) VALUES


('John Doe'),
('Alice Smith'),

Rohit S. Patil
18​

('Bob Johnson');

INSERT INTO passport (person_id, passport_number) VALUES


(1, 'P123456789'),
(2, 'P987654321'),
(3, 'P456789123');

To check if the data is inserted correctly:

SELECT p.id, p.name, ps.passport_number


FROM person p
LEFT JOIN passport ps ON p.id = ps.person_id;

Output:

Note: FOREIGN KEY (person_id) REFERENCES person(id): Links the passport to


the correct person.

2.​ One To Many/ Many To One:


Ex. A record in Table A can have multiple records in Table B.

CREATE TABLE department (


id SERIAL PRIMARY KEY,
name VARCHAR(100)
);

CREATE TABLE employee (


id SERIAL PRIMARY KEY,
name VARCHAR(100),
department_id INT,

Rohit S. Patil
19​

FOREIGN KEY(department_id) REFERENCES department(id)


);

INSERT INTO department (name) VALUES


('HR'),
('Finance'),
('Engineering');

INSERT INTO employee (name, department_id) VALUES


('Alice Johnson', 1), -- HR
('Bob Smith', 1), -- HR
('Charlie Brown', 2), -- Finance
('David White', 3), -- Engineering
('Eve Black', 3); -- Engineering

To check if the data is inserted correctly:

SELECT d.id, d.name,e.department_id, e.name from department d


LEFT JOIN employee e ON d.id = e.department_id
ORDER BY d.id;

Output:

Rohit S. Patil
20​

3.​ Many To Many:​



Example: Students & Courses (M:M Relationship)

●​ A student can enroll in multiple courses.​

●​ A course can have multiple students enrolled.​

●​ A junction table (student_course) links students and courses.

CREATE TABLE student (


id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);

CREATE TABLE course (


id SERIAL PRIMARY KEY,
title VARCHAR(100) NOT NULL
);

CREATE TABLE student_course (


student_id INT REFERENCES student(id) ON DELETE CASCADE,
course_id INT REFERENCES course(id) ON DELETE CASCADE,
PRIMARY KEY (student_id, course_id)
);

INSERT INTO student (name) VALUES


('Alice Johnson'),
('Bob Smith'),
('Charlie Brown');

INSERT INTO course (title) VALUES


('Mathematics'),
('Physics'),
('Computer Science');

INSERT INTO student_course (student_id, course_id) VALUES


(1, 1), -- Alice → Mathematics
(1, 2), -- Alice → Physics
(2, 1), -- Bob → Mathematics
(2, 3), -- Bob → Computer Science
(3, 2), -- Charlie → Physics
(3, 3); -- Charlie → Computer Science

Rohit S. Patil
21​

Retrieve Data with JOIN:

SELECT
s.id AS student_id,
s.name AS student_name,
c.id AS course_id,
c.title AS course_title
FROM student s
JOIN student_course sc ON s.id = sc.student_id
JOIN course c ON sc.course_id = c.id
ORDER BY s.id;

Output:

Rohit S. Patil
22​

JOINS: INNER JOIN, CROSS JOIN, FULL JOIN, LEFT JOIN, RIGHT JOIN

Let’s Take Two Table

1️⃣ INNER JOIN (Returns only matching records)

SELECT students.id, students.name, enrollments.course_name


FROM students
INNER JOIN enrollments ON students.id = enrollments.student_id;

Rohit S. Patil
23​

2️⃣ LEFT JOIN (All students, NULL if no match in enrollments)

SELECT students.id, students.name, enrollments.course_name


FROM students
LEFT JOIN enrollments ON students.id = enrollments.student_id;

3️⃣ RIGHT JOIN (All enrollments, NULL if no student exists)

SELECT students.id, students.name, enrollments.course_name


FROM students
RIGHT JOIN enrollments ON students.id = enrollments.student_id;

Rohit S. Patil
24​

4️⃣ FULL JOIN (All students and enrollments, NULL where no match)

SELECT students.id, students.name, enrollments.course_name


FROM students
FULL JOIN enrollments ON students.id = enrollments.student_id;

Rohit S. Patil
25​

5️⃣ CROSS JOIN (All possible combinations)

SELECT students.name, enrollments.course_name


FROM students
CROSS JOIN enrollments;

VIEWS:

Syntax: CREATE VIEW view_name AS


SELECT column1, column2, …
FROM table_name
WHERE condition;

Ex: CREATE VIEW student_courseinfo AS


SELECT

Rohit S. Patil
26​

​ s.id AS student_id,
​ s.name AS student_name,
​ c.id AS course_id,
​ c.title AS course_title
FROM student s
JOIN student_course sc ON s.id = sc.student_id
JOIN course c ON sc.course_id = c.id
ORDER BY s.id;

✅ Query the View: SELECT * FROM student_courseinfo;

Having clause:
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
customer_id INT NOT NULL,
total_amount DECIMAL(10,2) NOT NULL
);

INSERT INTO orders (customer_id, total_amount) VALUES


(101, 500.00),
(102, 700.00),
(101, 200.00),
(103, 900.00),
(102, 400.00);

Query the HAVING:


SELECT customer_id, SUM(total_amount) AS total_spent
FROM orders
GROUP BY customer_id
HAVING SUM(total_amount) > 800;

Output:

Rohit S. Patil
27​


CREATE INDEX creates an index on a table to improve query performance.

CREATE TABLE students (


id SERIAL PRIMARY KEY,
name TEXT,
age INT,
email TEXT
);

INSERT INTO students (name, age, email)


VALUES
('Alice Smith', 22, '[email protected]'),
('Bob Johnson', 19, '[email protected]'),
('Charlie Brown', 21, '[email protected]'),
('Diana White', 23, '[email protected]');

CREATE INDEX idx_students_email ON students(email);

SELECT * FROM students_one WHERE email = '[email protected]';

Output:

Rohit S. Patil
28​

GROUP BY ROLLUP and COALESCE:

CREATE TABLE sales (


id SERIAL PRIMARY KEY,
region TEXT,
category TEXT,
revenue NUMERIC
);

INSERT INTO sales (region, category, revenue) VALUES


('North', 'Electronics', 1000),
('North', 'Clothing', 500),
('South', 'Electronics', 700),
('South', 'Clothing', 300),
('East', 'Electronics', 800),
('East', 'Clothing', 600);

Query the COLESCE and GROUP BY ROLLUP:

SELECT
COALESCE(region, 'Total') AS region,
COALESCE(category, 'Subtotal') AS category,
SUM(revenue) AS total_revenue
FROM sales
GROUP BY ROLLUP (region, category)
ORDER BY region NULLS LAST, category NULLS LAST;

Rohit S. Patil
29​

Explanation:
1.​ ROLLUP (region, category):
○​ Groups by region and category, computing subtotals for each region and a
grand total.​

2.​ COALESCE(region, 'Total'):


○​ If region is NULL, replace it with "Total" (for grand total rows).​

3.​ COALESCE(category, 'Subtotal'):


○​ If category is NULL, replace it with "Subtotal" (for regional subtotals).​

4.​ ORDER BY region NULLS LAST, category NULLS LAST:


○​ Ensures subtotal and total rows appear at the end.

OUTPUT:

Rohit S. Patil
30​

Window Function:​

CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
class VARCHAR(10),
subject VARCHAR(50),
marks INT
);

INSERT INTO students (name, class, subject, marks) VALUES


('Alice', '10A', 'Math', 85),
('Bob', '10A', 'Math', 92),
('Charlie', '10A', 'Math', 78),
('David', '10A', 'Math', 88),
('Eve', '10A', 'Math', 85),
('Frank', '10B', 'Math', 95),
('Grace', '10B', 'Math', 89),
('Hank', '10B', 'Math', 90);

Query the Window Functions -

SELECT id, name, class, subject, marks,


​ RANK() OVER (PARTITION BY class ORDER BY marks DESC) AS rank,
​ DENSE_RANK() OVER (PARTITION BY class ORDER BY marks DESC) AS
dense_rank,
ROW_NUMBER() OVER (PARTITION BY class ORDER BY marks DESC) AS
row_number
FROM students;

Output:

Rohit S. Patil
31​

PostgreSQL's OVER() clause defines how a window function processes rows. It controls:

●​ Partitioning (PARTITION BY) – Divides rows into groups before applying the
function.
●​ Ordering (ORDER BY) – Defines the sequence in which the function processes rows.
●​ Framing (ROWS BETWEEN ... AND ...) – Specifies the range of rows for calculations
(optional)

RANK()​ Assigns a unique rank to rows, skipping numbers for ties.

DENSE_RANK()​ Assigns a unique rank without skipping numbers for ties.

ROW_NUMBER()​ Assigns a unique sequential number to each row.

Calculate the sum of Marks:


SELECT id, name, class, subject, marks,
SUM(marks) OVER (PARTITION BY class ORDER BY marks DESC) AS running_total
FROM students;

Output:

LAG() & LEAD():

LAG(): ​Fetches the value from the previous row.


LEAD(): Fetches the value from the next row.

Rohit S. Patil
32​

SELECT id, name, class, subject, marks,


LAG(marks) OVER (PARTITION BY class ORDER BY marks DESC) AS previous_marks,
LEAD(marks) OVER (PARTITION BY class ORDER BY marks DESC) AS next_marks
FROM students;

Output:

CTE(Common Table Expressions):

CREATE TABLE employees (


id SERIAL PRIMARY KEY,
name VARCHAR(50),
department VARCHAR(50),
salary INT
);

INSERT INTO employees (name, department, salary) VALUES


('Alice', 'HR', 5000),
('Bob', 'HR', 7000),
('Charlie', 'IT', 9000),
('David', 'IT', 12000),
('Eve', 'Sales', 4000),
('Frank', 'Sales', 8000);

Rohit S. Patil
33​

Use a CTE:

WITH avg_salary AS (
SELECT department, AVG(salary) AS dept_avg_salary
FROM employees
GROUP BY department
)
SELECT e.name, e.department, e.salary, a.dept_avg_salary
FROM employees e
JOIN avg_salary a ON e.department = a.department
WHERE e.salary > a.dept_avg_salary;

OUTPUT:

✅ Explanation
1️⃣ CTE (avg_salary) calculates the average salary per department.​
2️⃣ Main query joins employees with avg_salary to compare each employee’s salary with
the department average.​
3️⃣ . Filters out employees earning more than the department average.

Rohit S. Patil
34​


Rohit S. Patil

You might also like