You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lab6.org 8.4 KiB

1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #+title: Lab 6 Amirlan Sharipov (BS-CS21-01)
  2. #+author: Amirlan Sharipov (BS-CS21-01)
  3. * Disclaimer
  4. Please, use the lab6.sql file to read/copy the source code. Also, the html version of this document looks better than the pdf one.
  5. * Exercise 1
  6. ** Table creation and insertion
  7. I used the schema provided in the slides. And then manually inserted data into the tables.
  8. #+begin_src sql
  9. CREATE TABLE customers (
  10. customerId INT,
  11. customerName VARCHAR(50),
  12. city VARCHAR(50),
  13. PRIMARY KEY (customerId)
  14. );
  15. CREATE TABLE items (
  16. itemId INT,
  17. itemName VARCHAR(50),
  18. price FLOAT,
  19. PRIMARY KEY (itemId)
  20. );
  21. CREATE TABLE orders (
  22. orderId INT,
  23. customerId INT,
  24. date DATE,
  25. FOREIGN KEY (customerId) REFERENCES customers(customerId),
  26. PRIMARY KEY (orderId)
  27. );
  28. CREATE TABLE order_details (
  29. orderId INT,
  30. itemId INT,
  31. quantity INT,
  32. FOREIGN KEY (itemId) REFERENCES items(itemId),
  33. PRIMARY KEY (orderId, itemId)
  34. );
  35. INSERT INTO customers VALUES('101', 'Martin', 'Prague');
  36. INSERT INTO customers VALUES('107', 'Herman', 'Madrid');
  37. INSERT INTO customers VALUES('110', 'Pedro', 'Moscow');
  38. INSERT INTO items VALUES('3786', 'Net', 35.0);
  39. INSERT INTO items VALUES('4011', 'Racket', 65.0);
  40. INSERT INTO items VALUES('9132', 'Pack-3', 4.75);
  41. INSERT INTO items VALUES('5794', 'Pack-6', 5.0);
  42. INSERT INTO items VALUES('3141', 'Cover', 10.0);
  43. INSERT INTO orders VALUES('2301', '101', '2011-02-23');
  44. INSERT INTO orders VALUES('2302', '107', '2011-02-25');
  45. INSERT INTO orders VALUES('2303', '110', '2011-02-27');
  46. INSERT INTO order_details VALUES ('2301', '3786', 3);
  47. INSERT INTO order_details VALUES ('2301', '4011', 6);
  48. INSERT INTO order_details VALUES ('2301', '9132', 8);
  49. INSERT INTO order_details VALUES ('2302', '5794', 4);
  50. INSERT INTO order_details VALUES ('2303', '4011', 2);
  51. INSERT INTO order_details VALUES ('2303', '3141', 2);
  52. #+end_src
  53. ** Queries
  54. First query takes the sum of all prices * quantities groupped by the orders and sorts them.
  55. The second query does the same thing, groups by customers, sorts by sum of quantities (descending order) and takes the first result.
  56. #+begin_src sql
  57. SELECT order_details.orderId, SUM(items.price * order_details.quantity)
  58. FROM order_details
  59. INNER JOIN items on items.itemId=order_details.itemId
  60. group by order_details.orderId ORDER BY sum ASC;
  61. SELECT customers.customerName, customers.city FROM customers
  62. INNER JOIN orders ON customers.customerId=orders.customerId
  63. INNER JOIN order_details ON order_details.orderId=orders.orderId
  64. GROUP BY customers.customerId
  65. ORDER BY SUM(order_details.quantity) DESC
  66. LIMIT 1;
  67. #+end_src
  68. * Exercise 2
  69. ** Normalization
  70. I have several assumptions:
  71. - Any teacher can work at several schools at once (or change the school)
  72. - Room numbers don't depend on schools: the first number of the room name is not enough to assume the opposite
  73. - Teachers may teach several courses: it's an elementary school, usually teachers can teach anything in elementary schools
  74. *** 1NF
  75. It's almost in 1NF state. Each cell is already atomic, values of the same domain, etc. The only thing that's not there is the primary key. Let's say for now that the primary key is a tuple of school, teacher, course, room, grade, and book. This way there are no conflicts. It still looks like a mess, so I will normalize it further.
  76. *** 2NF
  77. Make new tables with relations for partial functional dependencies of non-prime attributes on candidate keys:
  78. - lessons (lessonId, schoolName, teacherName, courseName, roomName, gradeName)
  79. - books (bookId, bookName, publisherName)
  80. - loans (loanId, lessonId, bookId, loanDate)
  81. *** 3NF
  82. Make new tables (with appropriate IDs) with relations for transitive functional dependencies of non-prime attribute on candidate key:
  83. - schools (schoolId, schoolName)
  84. - teachers (teacherId, teacherName)
  85. - courses (courseId, courseName)
  86. - rooms (roomId, roomName)
  87. - grades (gradeId, gradeName)
  88. - publishers (publisherId, publisherName)
  89. - lessons (lessonId, schoolId, teacherId, courseId, roomId, gradeId)
  90. - books (bookId, bookName, publisherId)
  91. - loans (loanId, lessonId, bookId, loanDate)
  92. *** BCNF and 4NF
  93. Already satisfies.
  94. *** Code
  95. #+begin_src sql
  96. CREATE TABLE schools (
  97. schoolId SERIAL,
  98. schoolName VARCHAR(50),
  99. PRIMARY KEY (schoolId)
  100. );
  101. CREATE TABLE teachers (
  102. teacherId SERIAL,
  103. teacherName VARCHAR(30),
  104. PRIMARY KEY (teacherId)
  105. );
  106. CREATE TABLE courses (
  107. courseId SERIAL,
  108. courseName VARCHAR(40),
  109. PRIMARY KEY (courseId)
  110. );
  111. CREATE TABLE rooms (
  112. roomId SERIAL,
  113. roomName VARCHAR(40),
  114. PRIMARY KEY (roomId)
  115. );
  116. CREATE TABLE grades (
  117. gradeId SERIAL,
  118. gradeName VARCHAR(15),
  119. PRIMARY KEY (gradeId)
  120. );
  121. CREATE TABLE publishers (
  122. publisherId SERIAL,
  123. publisherName VARCHAR(30),
  124. PRIMARY KEY (publisherId)
  125. );
  126. CREATE TABLE books (
  127. bookId SERIAL,
  128. bookName VARCHAR(60),
  129. publisherId INT,
  130. FOREIGN KEY (publisherId) REFERENCES publishers(publisherId),
  131. PRIMARY KEY (bookId)
  132. );
  133. CREATE TABLE lessons (
  134. lessonId SERIAL,
  135. schoolId INT,
  136. teacherId INT,
  137. courseId INT,
  138. roomId INT,
  139. gradeId INT,
  140. FOREIGN KEY (teacherId) REFERENCES teachers(teacherId),
  141. FOREIGN KEY (courseId) REFERENCES courses(courseId),
  142. FOREIGN KEY (roomId) REFERENCES rooms(roomId),
  143. FOREIGN KEY (gradeId) REFERENCES grades(gradeId),
  144. PRIMARY KEY (lessonId)
  145. );
  146. CREATE TABLE loans (
  147. loanId SERIAL,
  148. lessonId INT,
  149. bookId INT,
  150. loanDate DATE,
  151. FOREIGN KEY (lessonId) REFERENCES lessons(lessonId),
  152. FOREIGN KEY (bookId) REFERENCES books(bookId),
  153. PRIMARY KEY (loanId)
  154. );
  155. INSERT INTO schools (schoolName)
  156. SELECT DISTINCT school FROM loan_books;
  157. INSERT INTO teachers (teacherName)
  158. SELECT DISTINCT teacher FROM loan_books;
  159. -- Inserted Numerical thinking 2 times because of case sensitivity. Not gonna change anything.
  160. INSERT INTO courses (courseName)
  161. SELECT DISTINCT course FROM loan_books;
  162. INSERT INTO rooms (roomName)
  163. SELECT DISTINCT room FROM loan_books;
  164. INSERT INTO grades (gradeName)
  165. SELECT DISTINCT grade FROM loan_books;
  166. INSERT INTO publishers (publisherName)
  167. SELECT DISTINCT publisher FROM loan_books;
  168. INSERT INTO books (bookName, publisherId)
  169. SELECT DISTINCT loan_books.book,
  170. publishers.publisherId FROM loan_books
  171. INNER JOIN publishers ON
  172. publishers.publisherName=loan_books.publisher;
  173. INSERT INTO lessons (schoolId, teacherId, courseId, roomId, gradeId)
  174. SELECT DISTINCT schools.schoolId, teachers.teacherId,
  175. courses.courseId, rooms.roomId, grades.gradeId FROM loan_books
  176. INNER JOIN schools ON schools.schoolName=loan_books.school
  177. INNER JOIN teachers ON teachers.teacherName=loan_books.teacher
  178. INNER JOIN courses ON courses.courseName=loan_books.course
  179. INNER JOIN rooms ON rooms.roomName=loan_books.room
  180. INNER JOIN grades ON grades.gradeName=loan_books.grade;
  181. INSERT INTO loans (lessonId, bookId, loanDate)
  182. SELECT DISTINCT lessons.lessonId, books.bookId,
  183. loan_books.loanDate FROM loan_books
  184. INNER JOIN schools ON schools.schoolName=loan_books.school
  185. INNER JOIN teachers ON teachers.teacherName=loan_books.teacher
  186. INNER JOIN courses ON courses.courseName=loan_books.course
  187. INNER JOIN rooms ON rooms.roomName=loan_books.room
  188. INNER JOIN grades ON grades.gradeName=loan_books.grade
  189. INNER JOIN books ON books.bookName=loan_books.book
  190. INNER JOIN lessons ON lessons.gradeId=grades.gradeId
  191. and lessons.roomId=rooms.roomId
  192. and lessons.courseId=courses.courseId
  193. and lessons.teacherId=teachers.teacherId;
  194. #+end_src
  195. ** Queries
  196. The first query list all the schools that borrowed the books of every publisher using DISTINCT keyword.
  197. The second query orders the results from each school, and takes only 1 loan that has the highest loanDate for each school.
  198. #+begin_src sql
  199. SELECT DISTINCT publishers.publisherName, books.bookName,
  200. schools.schoolName FROM books
  201. INNER JOIN loans ON loans.bookId=books.bookId
  202. INNER JOIN lessons ON lessons.lessonId=loans.lessonId
  203. INNER JOIN schools ON schools.schoolId=lessons.schoolId
  204. INNER JOIN publishers ON publishers.publisherId=books.publisherId
  205. ORDER BY publishers.publisherName;
  206. SELECT DISTINCT ON (schools.schoolName) schools.schoolName,
  207. publishers.publisherName, books.bookName FROM loans
  208. INNER JOIN lessons ON lessons.lessonId=loans.lessonId
  209. INNER JOIN schools ON schools.schoolId=lessons.schoolId
  210. INNER JOIN books ON books.bookId=loans.bookId
  211. INNER JOIN publishers ON publishers.publisherId=books.publisherId
  212. ORDER BY schools.schoolName, loans.loanDate DESC, 1;
  213. #+end_src