Академический Документы
Профессиональный Документы
Культура Документы
If you installed PostgreSQL on Windows operating system, along with the DBMS the tool to access the
DBMS and perform queries -. pgAdmin will be installed. If you have not installed pgAdmin along with
PostgreSQL DBMS, it can be downloaded from http://www.pgadmin.org/download/.
PgAdmin will recognize local instance of postgreSQL server and will create the appropriate object Server.
Using gAdmin program connect to the PostgreSQL DBMS as a user postgres. Create a database e.g.
advancedSQL (right-click on Databases - New Database, Name: advancedSQL, Owner: postgres). Refresh
the content of the Databases sub tree (right-click on Databases - Refresh), select the advancedSQL and
open a query window (Tools - Query Tool).
Set the format of the Date data type in dd/mm/yyyy performing the following command:
set DateStyle ='SQL, DMY'
studID
1
3
1
examDate
01/06/2013
01/06/2013
01/07/2013
grade
1
5
4
Excercise 2.
Calculate total number of points and rank for each student and course.
Look at the slide Motivation example 1 from the first lectures.
studTest
courseID
1
1
1
studID
1
2
3
testType
1DZ
1DZ
1DZ
points
5.00
10.00
5.00
Excercise 3.
Determine the total number of points and ranking for each student in each course. In addition,
determine the average value of total points for the students at the course.
Excercises 4-6.
For excercises 4-6 the relations orgUnit, employee, empPayment and project are used. Their schema and
content is defined with SQL statements in file excercises1.sql. Scheme and sample of the contents of
relations is shown in the following figure.
orgUnit
orgUnitID
1
2
3
empPayment
empID
1
1
1
orgUnitName
Grocery in Radnika
Grocery in Vukovarska
Grocery in Ilica
employee
empDl FName
1
Ana
2
ime
3
Petra
...
LName
Par
Knez
Pili
orgUnitId
1
1
1
supEmpId
1
1
project
projectID
234
764
paymentDate
01/01/2013
01/02/2013
01/03/2013
respEmpID
1
2
amount
4700.00
4700.00
4700.00
beginDate
01/3/2013
05/4/2013
endDate
20/7/2013
15/8/2013
FName
Ana
Ana
Ana
Ana
Ana
paymentDate
2013-01-10
2013-02-10
2013-03-10
2013-04-10
2013-05-10
amount
4700.00
4700.00
4700.00
4700.00
4700.00
totAmount
4700.00
9400.00
14100.00
14100.00
14100.00
Excercise 5.
For each organizational unit print information about the best and worst-paid employee in the following
format:
orgUnitName
Grocery in Ilica
Grocery in Ilica
LName
Mili
Buri
FName
Petar
Marija
totAmount
26100.00
96900.00
comment
worst paid
best paid
Excercise 6.
For each employee determine number of salary changes. Presend data in the following format:
LName
Mili
Knez
Jeli
Par
FName
Petar
ime
Marko
Ana
noOfChanges
0
3
0
2
Excercise 7.
For each employee determine the total amount earned and the percentage of the amount of the best
paid employees in an organizational unit, and in the whole company. Present data in the following
format:
orgUnitName
Grocery in Radnika
Grocery in Radnika
Grocery in Radnika
Grocery in Vukovarska
Grocery in Vukovarska
LName
Par
Knez
Pili
Kralj
Jeli
FName
Ana
ime
Petra
Anita
Marko
totAmount
43000.00
40850.00
32400.00
78900.00
67500.00
percOfMaxOU
100.00
95.00
75.34
100.00
85.55
percOfMaxC
44.37
42.15
33.43
81.42
69.65
Recursive queries
Excercise 8.
Find people with whom the person ana123@hotmail.com is connected directly or through a friend.
Consider only friendships in which ana123@hotmail.com (or her friends, friends of friends, etc.). is
initiator (foaf.person1 = 'ana123@hotmail.com'), but also those in which someone else has initiated a
friendship (foaf. Person2 = 'ana123@hotmail.com' and so on.).
foaf
person1
person2
ana123@hotmail.com
zecG@gmail.com
klaraB@gmail.com
zecG@gmail.com
Iva.malic@fer.hr
klaraB@gmail.com
jon.doe@info.hr
cat56@hotmail.com
...
zecG@gmail.com
iva.malic@fer.hr
ana123@hotmail.com
jezV@hotmail.com
jezV@hotmail.com
mia95@yahoo.com
klaraB@gmail.com
jon.doe@info.hr
Excercise 9.
For each month in which the project with code 746 was active, calculate the total amounts paid to
employees on the project for the duration of the project.
Pivoting
Excercise 10.
For each year and month calculate total amount paid in the following format:
year
january
february
march
april
may
june
July
august
48890.00
2013
47840.00
47840.00
48070.00
48840.00
48890.00
Excercise 11.
For employees in organizational units Grocery in Radnika, Grocery in Vukovarska and Grocery in Ilica
print total amount paid in the following format:
year
Grocery in Radnika
Grocery in Vukovarska
Grocery in Ilica
2013
177420.00
116250.00
146400.00
SOLUTIONS:
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
exam
exam
exam
exam
exam
exam
exam
exam
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
(1,
(1,
(1,
(1,
(1,
(1,
(2,
(2,
1,
3,
1,
2,
4,
5,
1,
2,
'01/06/2013',
'01/06/2013',
'01/07/2013',
'01/07/2013',
'01/07/2013',
'01/07/2013',
'01/07/2013',
'01/07/2013',
1);
5);
4);
5);
3);
2);
3);
2);
Excercise 2.
CREATE TABLE studTest (
courseID int NOT NULL,
studID int NOT NULL,
testType CHAR(5) NOT NULL,
points numeric (5,2) NOT NULL);-INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
studTest
studTest
studTest
studTest
studTest
studTest
studTest
studTest
studTest
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
(1,
(1,
(1,
(1,
(1,
(1,
(2,
(2,
(2,
1,
2,
3,
1,
2,
3,
1,
2,
3,
'1DZ',
5.00);
'1DZ',
10.00);
'1DZ',
5.00);
'MI', 10.00);
'MI', 5.00);
'MI', 20.00);
'MI', 20.00);
'MI', 25.00);
'MI', 30.00);
SELECT courseID
, studID
, SUM(points) totPoints
, rank () OVER (PARTITION BY courseID ORDER BY SUM(points)DESC) AS rank
FROM studTest
GROUP BY courseID, studID
ORDER BY courseID, rank
Excercise 3.
CREATE TABLE and INSERT statements are eyual to statements in previous excercise.
SELECT courseID
, studID
, SUM (points) totPoints
, rank () OVER (partition by courseID ORDER BY SUM(points) DESC) AS rank
, AVG(SUM(points)) OVER (partition by courseID) AS avgTotPoints
FROM studTest
GROUP BY courseID, studID
ORDER BY courseID, rank
Excercise 4.
select LName, FName, empPayment.paymentDate, amount
, SUM(amount) OVER (PARTITION BY empPayment.empID
ORDER BY paymentDate
ROWS 3 PRECEDING) totAmount
from empPayment, employee
where empPayment.empID = employee.empID
Excercise 5.
To print the comments 'best paid' or 'worst paid' we need conditional statement CASE. This is the syntax
of the CASE statement in PostgreSQL:
CASE WHEN condition THEN result
[WHEN ...]
[ELSE result]
END
Ranking of the employees in the organizational unit where the highest ranked employee is the one with
the highest income:
rank () OVER (PARTITION BY orgUnitName
ORDER BY SUM(amount) DESC)
maxA
Notice that by using PARTITION BY orgUnitName we defined partitions so that the same partition
contains tuples belonging to the same organizational unit.
The following query we use to get data about the total amount of incomes and ranks of employees
within their organizational units:
SELECT orgUnitName, employee.empID
, LName, FName, SUM(amount) totAmount
, rank () OVER (PARTITION BY orgUnitName
ORDER BY SUM(amount) DESC) maxA
, rank () OVER (PARTITION BY orgUnitName
ORDER BY SUM(amount))
minA
FROM empPayment, employee, orgUnit
WHERE empPayment.empID = employee.empID
AND employee.orgUnitID = orgUnit.orgUnitID
GROUP BY employee.orgUnitID, orgUnit.orgUnitName
, employee.empID, LName, FName
empID
8
7
6
3
1
2
5
4
LName
Mili
Rendi
Buri
Pili
Par
Knez
Jeli
Kralj
FName
Petar
Slavica
Marija
Petra
Ana
ime
Marko
Anita
totAmount
26100.00
54420.00
96900.00
32400.00
42900.00
43620.00
67500.00
78900.00
maxA
3
2
1
3
2
1
2
1
minA
1
2
3
1
2
3
1
2
The above query is named rankPayment and nested in the outer query:
SELECT rankPayment.*
, CASE
WHEN rankPayment.bestPayed = 1 AND
rankPayment.worstPayed > 1 THEN 'best paid'
WHEN rankPayment.bestPayed > 1 AND
rankPayment.worstPayed = 1 THEN 'worst paid'
END AS comment
FROM (
SELECT orgUnitName, employee.empID
, LName, FName, SUM(amount) totAmount
, rank () OVER (PARTITION BY orgUnitName
ORDER BY SUM(amount) DESC)
bestPayed
, rank () OVER (PARTITION BY orgUnitName
ORDER BY SUM(amount))
worstPayed
FROM empPayment, employee, orgUnit
WHERE empPayment.empID = employee.empID
AND employee.orgUnitID = orgUnit.orgUnitID
GROUP BY employee.orgUnitID, orgUnit.orgUnitName
, employee.empID, LName, FName
) rankPayment
WHERE rankPayment.bestPayed = 1 OR rankPayment.worstPayed = 1
Result:
orgUnitName
Grocery in Ilica
Grocery in Ilica
Grocery in Radnika
Grocery in Radnika
Grocery in Vukovarska
Grocery in Vukovarska
LName
Mili
Buri
Pili
Knez
Jeli
Kralj
FName
Petar
Marija
Petra
ime
Marko
Anita
totAmount
26100.00
96900.00
32400.00
43620.00
67500.00
78900.00
comment
worst paid
best paid
worst paid
best paid
worst paid
best paid
Whatshould be changed in the above query to obtain information on the 2 best and 2 worst paid
employees in each organizational unit?
Excercise 6.
It is necessary to create a partition for each employee (PARTITION BY empPayment.empID), and sort
rows within the partition by payment date (ORDER BY paymentDate). Amount paid for each row is
compared with previously paid amount lag(amount) - by default offset is 1 and lag retrieves row (i.e.
attribute amount) that immediately preceded the current row. Any change in the amount will be
marked with 1 and unchanged amount with value 0.
LName
FName
amount
paymentDate
changed
1
1
1
1
1
1
1
1
1
Par
Par
Par
Par
Par
Par
Par
Par
Par
Ana
Ana
Ana
Ana
Ana
Ana
Ana
Ana
Ana
4700.00
4700.00
4700.00
4700.00
4750.00
4750.00
4900.00
4900.00
4900.00
2013-01-10
2013-02-10
2013-03-10
2013-04-10
2013-05-10
2013-06-10
2013-07-10
2013-08-10
2013-09-10
0
0
0
0
1
0
1
0
0
The above query is named paymentChanges and nested in the outer query. Number of salary changes is
determined by summing column changed.
SELECT LName, FName, SUM(changed) noOfChanges
FROM
(SELECT employee.empID, LName, FName
, CASE
WHEN lag(amount) OVER (PARTITION BY empPayment.empID
ORDER BY paymentDate) != amount THEN 1
ELSE 0
END changed
FROM empPayment, employee
WHERE empPayment.empID = employee.empID) AS paymentChanges
GROUP BY paymentChanges.empID, paymentChanges.LName, paymentChanges.FName
Excercise 7.
SELECT orgUnitName
, LName, FName, SUM(amount) totAmount
, 100* SUM(amount)
/nth_value (SUM(amount),1) OVER (PARTITION BY orgUnitName ORDER BY
SUM(amount) DESC )
percOfMaxOU
, 100* SUM(amount)
/nth_value (SUM(amount),1) OVER (ORDER BY SUM(amount) DESC)
percOfMaxC
FROM empPayment, employee, orgUnit
WHERE empPayment.empID = employee.empID
AND employee.orgUnitID = orgUnit.orgUnitID
GROUP BY employee.orgUnitID, orgUnit.orgUnitName
, employee.empID, LName, FName
ORDER BY employee.orgUnitID, orgUnit.orgUnitName, SUM(amount) DESC
Recursive queries
Excercise 8.
create table foaf (
person1 char(50) not null,
person2 char(50) not null);
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
foaf
foaf
foaf
foaf
foaf
foaf
foaf
foaf
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
('ana123@hotmail.com',
('zecG@gmail.com',
('klaraB@gmail.com',
('zecG@gmail.com',
('iva.malic@fer.hr',
('klaraB@gmail.com',
('jon.doe@info.hr',
('cat56@hotmail.com',
'zecG@gmail.com');
'iva.malic@fer.hr');
'ana123@hotmail.com');
'jezV@hotmail.com');
'jezV@hotmail.com');
'mia95@yahoo.com');
'klaraB@gmail.com');
'jon.doe@info.hr');
Excercise 9.
Using CTE we will store store data about employees and superior (parent) employees recursively into a
temporary relation employees.
WITH RECURSIVE employees (empID, supEmpID) AS
( (SELECT empID, supEmpID FROM employee)
UNION
(SELECT employees.empID, employee.supEmpID
FROM employees, employee
WHERE employees.supEmpID = employee.empID)
)
SELECT * FROM employees
WHERE empID = 2 OR supEmpID = 2
1
2
2
2
2
2
Employee in charge for the the project (project.respEmpID) with code 746 should be equal to the
superior employee (employees.supEmpID) for the rows shown in the table above.
Since the employee with code 2 has no tuple with supEmpID = 2, and we want his income included in
the total income of employees on the project, we will solve this detail with the following condition:
(project.respEmpID = employees.supEmpID OR
project.respEmpID = employees.empID AND
Complete solution:
WITH RECURSIVE employees (empID, supEmpID) AS
( (SELECT empID, supEmpID FROM employee)
UNION
(SELECT employees.empID, employee.supEmpID
FROM employees, employee
WHERE employees.supEmpID = employee.empID)
)
SELECT EXTRACT (MONTH FROM paymentDate) AS month, SUM(amount) AS totAmount
FROM project, employees, empPayment
WHERE (project.respEmpID = employees.supEmpID OR
project.respEmpID = employees.empID AND
employees.supEmpID IS NOT NULL)
AND empPayment.empID = employees.empID
AND empPayment.paymentDate BETWEEN project.beginDate AND project.endDate
AND project.projectID = 746
GROUP BY month --EXTRACT (MONTH FROM paymentDate)
ORDER BY month --EXTRACT (MONTH FROM paymentDate)
Pivoting
Excercise 10.
CREATE EXTENSION tablefunc;
CREATE TEMP TABLE month
(monthOrd int);
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
month
month
month
month
month
month
month
month
month
month
month
month
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
( 2);
( 3);
( 4);
( 1);
( 5);
( 6);
( 7);
( 8);
( 9);
(10);
(11);
(12);
SELECT *
FROM crosstab(
'SELECT CAST(EXTRACT(YEAR FROM paymentDate) AS int) AS godina
, CAST(EXTRACT(MONTH FROM paymentDate) AS int) AS month
, CAST(SUM(amount) AS NUMERIC (10,2))
FROM empPayment
GROUP BY godina, month
ORDER BY godina, month'
, 'SELECT monthOrd FROM month ORDER BY monthOrd')
AS pivotTable (godina INT, sijeanj NUMERIC(10,2), veljaa NUMERIC(10,2)
, oujak NUMERIC(10,2), travanj NUMERIC(10,2), svibanj NUMERIC(10,2)
, lipanj NUMERIC(10,2), srpanj NUMERIC(10,2), kolovoz NUMERIC(10,2)
, rujan NUMERIC(10,2), listopad NUMERIC(10,2), studeni NUMERIC(10,2)
, prosinac NUMERIC(10,2))
ORDER BY godina
Excercise 11.
SELECT *
FROM crosstab(
'SELECT CAST(EXTRACT(YEAR FROM paymentDate) AS int) AS godina
, orgUnit.orgUnitName
, CAST(SUM(amount) AS NUMERIC (10,2))
FROM empPayment, employee, orgUnit
WHERE empPayment.empID = employee.empID
AND employee.orgUnitID = orgUnit.orgUnitID
AND orgUnit.orgUnitName IN (''Grocery in Ilica''
, ''Grocery in Radnika'', ''Grocery in Vukovarska'')
GROUP BY godina, orgUnit.orgUnitName
ORDER BY godina, orgUnit.orgUnitName')
AS pivotTable (godina INT, GroceryIlica NUMERIC(10,2)
, GroceryRadnika NUMERIC(10,2)
, GroceryVukovarska NUMERIC(10,2))
ORDER BY godina