├── .gitignore ├── prisma ├── migrations │ ├── migration_lock.toml │ └── 20230817060919_init │ │ └── migration.sql └── schema.prisma ├── src ├── index.ts ├── modules │ ├── enrollment │ │ ├── enrollment.route.ts │ │ ├── enrollment.controller.ts │ │ └── enrollment.service.ts │ ├── courses │ │ ├── courses.route.ts │ │ ├── courses.service.ts │ │ └── courses.controller.ts │ └── students │ │ ├── students.route.ts │ │ ├── students.controller.ts │ │ └── students.service.ts └── app.ts ├── package.json ├── LICENCE ├── PostgreSQL_Assignment.sql ├── readme.md └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # Keep environment variables out of version control 3 | .env 4 | # gitignore 5 | -------------------------------------------------------------------------------- /prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "postgresql" -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client"; 2 | import app from "./app"; 3 | // index cheak the server 4 | const prisma = new PrismaClient(); 5 | const port = process.env.PORT || 5000; 6 | async function main() { 7 | app.listen(port, () => { 8 | console.log(`Server running at ${port}`); 9 | }); 10 | } 11 | 12 | main(); 13 | -------------------------------------------------------------------------------- /src/modules/enrollment/enrollment.route.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { EnrollController } from "./enrollment.controller"; 3 | // enrollment routes all student 4 | const router = express.Router(); 5 | // get all student name who enrolled to Next.js course 6 | router.get("/enroll-course", EnrollController.getEnrolledStudentName); 7 | // insert into enrollment table 8 | router.post("/enroll-course", EnrollController.insertIntoDB); 9 | 10 | export const EnrollRoutes = router; 11 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | import express, { Application } from "express"; 2 | import cors from "cors"; 3 | import { StudentRoutes } from "./modules/students/students.route"; 4 | import { CourseRoutes } from "./modules/courses/courses.route"; 5 | import { EnrollRoutes } from "./modules/enrollment/enrollment.route"; 6 | // Apps ts 7 | const app: Application = express(); 8 | app.use(express.json()); 9 | app.use(cors()); 10 | app.use(express.urlencoded({ extended: true })); 11 | 12 | app.use("/api/v1/student", StudentRoutes); 13 | app.use("/api/v1/course", CourseRoutes); 14 | app.use("/api/v1/enrollment", EnrollRoutes); 15 | 16 | export default app; 17 | -------------------------------------------------------------------------------- /src/modules/courses/courses.route.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { CourseController } from "./courses.controller"; 3 | // Courses Route 4 | const router = express.Router(); 5 | 6 | // add course route 7 | router.post("/add-course", CourseController.insertIntoDB); 8 | // Delete all courses that have no students enrolled. 9 | router.delete("/delete-course", CourseController.deleteCourseWithNoStudents); 10 | // Retrieve the course names and the number of students enrolled in each course. 11 | router.get( 12 | "/get-student-and-coursename", 13 | CourseController.getCourseNameAndNumberOfStudents 14 | ); 15 | 16 | export const CourseRoutes = router; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "prisma-assignment", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon ./src/index.ts", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@types/cors": "^2.8.13", 15 | "@types/express": "^4.17.17", 16 | "@types/node": "^20.5.0", 17 | "prisma": "^5.1.1", 18 | "ts-node": "^10.9.1", 19 | "typescript": "^5.1.6" 20 | }, 21 | "dependencies": { 22 | "@prisma/client": "^5.1.1", 23 | "cors": "^2.8.5", 24 | "express": "^4.18.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/modules/students/students.route.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { StudentController } from "./students.controller"; 3 | // Studnet Route 4 | const router = express.Router(); 5 | // get all students 6 | router.get("/", StudentController.getStudents); 7 | // Update the status of the student with the highest total (frontend_mark + backend_mark) mark to 'Awarded' 8 | router.patch("/update-status", StudentController.updateStudentStatus); 9 | // insert into student table 10 | router.post("/add-student", StudentController.insertIntoDB); 11 | // Retrieve the names of students using a limit of 2, starting from the 3rd student. 12 | router.get("/get-student-pagination", StudentController.getEnrolledStudentName); 13 | // Calculate and display the average age of all students. 14 | router.get("/get-average-age", StudentController.getAverageAge); 15 | // Retrieve the names of students whose email addresses contain 'example.com'. 16 | router.get("/get-student-email", StudentController.getStudentEmail); 17 | 18 | export const StudentRoutes = router; 19 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Hazrat Ali 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | // Schema Prisma 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | // Schema 8 | datasource db { 9 | provider = "postgresql" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model Student { 14 | student_id Int @id @default(autoincrement()) 15 | student_name String @db.VarChar(255) 16 | age Int 17 | email String @db.VarChar(255) 18 | frontend_mark Int 19 | backend_mark Int 20 | status String? 21 | enrollment Enrollment[] 22 | 23 | @@map("students") 24 | } 25 | 26 | model Course { 27 | course_id Int @id @default(autoincrement()) 28 | course_name String @db.VarChar(255) 29 | credits Int 30 | enrollment Enrollment[] 31 | 32 | @@map("courses") 33 | } 34 | 35 | model Enrollment { 36 | enrollment_id Int @id @default(autoincrement()) 37 | student_id Int 38 | student Student @relation(fields: [student_id], references: [student_id]) 39 | course_id Int 40 | course Course @relation(fields: [course_id], references: [course_id]) 41 | 42 | @@map("enrollment") 43 | } 44 | -------------------------------------------------------------------------------- /src/modules/courses/courses.service.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient, Course } from "@prisma/client"; 2 | // Courses Service 3 | const prisma = new PrismaClient(); 4 | 5 | const insertIntoDB = async (data: Course): Promise => { 6 | const result = await prisma.course.create({ 7 | data, 8 | }); 9 | return result; 10 | }; 11 | 12 | const deleteCourseWithNoStudents = async () => { 13 | const result = await prisma.course.deleteMany({ 14 | where: { 15 | enrollment: { 16 | none: {}, 17 | }, 18 | }, 19 | }); 20 | return result; 21 | }; 22 | 23 | const getCourseNameAndNumberOfStudents = async () => { 24 | const courseEnrollments = await prisma.course.findMany({ 25 | select: { 26 | course_name: true, 27 | enrollment: { 28 | select: { 29 | student_id: true, 30 | }, 31 | }, 32 | }, 33 | }); 34 | 35 | const courseEnrollmentCounts = courseEnrollments.map((course) => ({ 36 | course_name: course.course_name, 37 | students_enrolled: course.enrollment.length, 38 | })); 39 | 40 | return courseEnrollmentCounts; 41 | }; 42 | 43 | export const CourseService = { 44 | insertIntoDB, 45 | deleteCourseWithNoStudents, 46 | getCourseNameAndNumberOfStudents, 47 | }; 48 | -------------------------------------------------------------------------------- /prisma/migrations/20230817060919_init/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "students" ( 3 | "student_id" SERIAL NOT NULL, 4 | "student_name" VARCHAR(255) NOT NULL, 5 | "age" INTEGER NOT NULL, 6 | "email" VARCHAR(255) NOT NULL, 7 | "frontend_mark" INTEGER NOT NULL, 8 | "backend_mark" INTEGER NOT NULL, 9 | "status" TEXT, 10 | 11 | CONSTRAINT "students_pkey" PRIMARY KEY ("student_id") 12 | ); 13 | 14 | -- CreateTable 15 | CREATE TABLE "courses" ( 16 | "course_id" SERIAL NOT NULL, 17 | "course_name" VARCHAR(255) NOT NULL, 18 | "credits" INTEGER NOT NULL, 19 | 20 | CONSTRAINT "courses_pkey" PRIMARY KEY ("course_id") 21 | ); 22 | 23 | -- CreateTable 24 | CREATE TABLE "enrollment" ( 25 | "enrollment_id" SERIAL NOT NULL, 26 | "student_id" INTEGER NOT NULL, 27 | "course_id" INTEGER NOT NULL, 28 | 29 | CONSTRAINT "enrollment_pkey" PRIMARY KEY ("enrollment_id") 30 | ); 31 | 32 | -- AddForeignKey 33 | ALTER TABLE "enrollment" ADD CONSTRAINT "enrollment_student_id_fkey" FOREIGN KEY ("student_id") REFERENCES "students"("student_id") ON DELETE RESTRICT ON UPDATE CASCADE; 34 | 35 | -- AddForeignKey 36 | ALTER TABLE "enrollment" ADD CONSTRAINT "enrollment_course_id_fkey" FOREIGN KEY ("course_id") REFERENCES "courses"("course_id") ON DELETE RESTRICT ON UPDATE CASCADE; 37 | -------------------------------------------------------------------------------- /src/modules/courses/courses.controller.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | import { CourseService } from "./courses.service"; 3 | // Courses Controller 4 | const insertIntoDB = async (req: Request, res: Response) => { 5 | try { 6 | const result = await CourseService.insertIntoDB(req.body); 7 | res.send({ 8 | succes: true, 9 | message: "Course Added successfully!", 10 | data: result, 11 | }); 12 | } catch (err) { 13 | res.send(err); 14 | } 15 | }; 16 | 17 | const deleteCourseWithNoStudents = async (req: Request, res: Response) => { 18 | try { 19 | const result = await CourseService.deleteCourseWithNoStudents(); 20 | res.send({ 21 | succes: true, 22 | message: "Course deleted successfully!", 23 | data: result, 24 | }); 25 | } catch (err) { 26 | res.send(err); 27 | } 28 | }; 29 | 30 | const getCourseNameAndNumberOfStudents = async (req: Request, res: Response) => { 31 | try { 32 | const result = await CourseService.getCourseNameAndNumberOfStudents(); 33 | res.send({ 34 | succes: true, 35 | message: "data fetched successfully!", 36 | data: result, 37 | }); 38 | } catch (err) { 39 | res.send(err); 40 | } 41 | }; 42 | 43 | export const CourseController = { 44 | insertIntoDB, 45 | deleteCourseWithNoStudents, 46 | getCourseNameAndNumberOfStudents, 47 | }; 48 | -------------------------------------------------------------------------------- /src/modules/enrollment/enrollment.controller.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | import { EnrollmentService } from "./enrollment.service"; 3 | // enrollment Controller 4 | const insertIntoDB = async (req: Request, res: Response) => { 5 | try { 6 | const result = await EnrollmentService.insertIntoDB(req.body); 7 | res.send({ 8 | succes: true, 9 | message: "Course Enrolled successfully!", 10 | data: result, 11 | }); 12 | } catch (err) { 13 | res.send(err); 14 | } 15 | }; 16 | 17 | // const insertOrUpdateProfile = async (req: Request, res: Response) => { 18 | // try { 19 | // const result = await UserService.insertOrUpdateProfile(req.body); 20 | // res.send({ 21 | // succes: true, 22 | // message: "Profile created/updated successfully!", 23 | // data: result, 24 | // }); 25 | // } catch (err) { 26 | // res.send(err); 27 | // } 28 | // }; 29 | 30 | const getEnrolledStudentName = async (req: Request, res: Response) => { 31 | try { 32 | const result = await EnrollmentService.getEnrolledStudentName(); 33 | res.send({ 34 | succes: true, 35 | message: "data fetched successfully!", 36 | data: result, 37 | }); 38 | } catch (err) { 39 | res.send(err); 40 | } 41 | }; 42 | 43 | 44 | 45 | export const EnrollController = { 46 | insertIntoDB, 47 | getEnrolledStudentName, 48 | // insertOrUpdateProfile, 49 | // getUsers, 50 | // getSingleUser, 51 | }; 52 | -------------------------------------------------------------------------------- /src/modules/enrollment/enrollment.service.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient, Course, Enrollment } from "@prisma/client"; 2 | // Enrollment Service 3 | const prisma = new PrismaClient(); 4 | 5 | const insertIntoDB = async (data: Enrollment): Promise => { 6 | const result = await prisma.enrollment.create({ 7 | data, 8 | }); 9 | return result; 10 | }; 11 | 12 | // const insertOrUpdateProfile = async (data: Profile): Promise => { 13 | // const isExist = await prisma.profile.findUnique({ 14 | // where: { 15 | // userId: data.userId, 16 | // }, 17 | // }); 18 | 19 | // if (isExist) { 20 | // const result = await prisma.profile.update({ 21 | // where: { 22 | // userId: data.userId, 23 | // }, 24 | // data: { 25 | // bio: data.bio, 26 | // }, 27 | // }); 28 | 29 | // return result; 30 | // } 31 | 32 | // const result = await prisma.profile.create({ 33 | // data, 34 | // }); 35 | // return result; 36 | // }; 37 | 38 | // const getUsers = async () => { 39 | // // const result = await prisma.user.findMany({ 40 | // // // select: { 41 | // // // email: true, 42 | // // // name: true 43 | // // // } 44 | // // include: { 45 | // // profile: true 46 | // // } 47 | // // }); 48 | 49 | // const result = await prisma.$queryRaw`select * from users`; 50 | // return result; 51 | // }; 52 | 53 | // const getSingleUser = async (id: number) => { 54 | // const result = await prisma.user.findUnique({ 55 | // where: { 56 | // id, 57 | // }, 58 | // include: { 59 | // profile: true, 60 | // }, 61 | // }); 62 | // return result; 63 | // }; 64 | 65 | // get all student name who enrolled to Next.js course 66 | const getEnrolledStudentName = async () => { 67 | 68 | const result = await prisma.enrollment.findMany({ 69 | where: { 70 | course_id: 1, 71 | }, 72 | select: { 73 | student: { 74 | select: { 75 | student_name: true, 76 | }, 77 | }, 78 | }, 79 | }); 80 | 81 | return result; 82 | }; 83 | 84 | export const EnrollmentService = { 85 | insertIntoDB, 86 | getEnrolledStudentName, 87 | // insertOrUpdateProfile, 88 | // getUsers, 89 | // getSingleUser, 90 | }; 91 | -------------------------------------------------------------------------------- /src/modules/students/students.controller.ts: -------------------------------------------------------------------------------- 1 | import { Request, Response } from "express"; 2 | import { StudentService } from "./students.service"; 3 | // Student Controller 4 | const insertIntoDB = async (req: Request, res: Response) => { 5 | try { 6 | const result = await StudentService.insertIntoDB(req.body); 7 | res.send({ 8 | succes: true, 9 | message: "Student Added successfully!", 10 | data: result, 11 | }); 12 | } catch (err) { 13 | res.send(err); 14 | } 15 | }; 16 | 17 | const updateStudentStatus = async (req: Request, res: Response) => { 18 | try { 19 | const result = await StudentService.updateStudentStatus(); 20 | res.send({ 21 | succes: true, 22 | message: "Student status updated successfully!", 23 | data: result, 24 | }); 25 | } catch (err) { 26 | res.send(err); 27 | } 28 | }; 29 | 30 | const getStudents = async (req: Request, res: Response) => { 31 | try { 32 | const result = await StudentService.getStudents(); 33 | res.send({ 34 | succes: true, 35 | message: "data fetched successfully!", 36 | data: result, 37 | }); 38 | } catch (err) { 39 | res.send(err); 40 | } 41 | }; 42 | 43 | const getEnrolledStudentName = async (req: Request, res: Response) => { 44 | try { 45 | const result = await StudentService.getEnrolledStudentName(); 46 | res.send({ 47 | succes: true, 48 | message: "data fetched successfully!", 49 | data: result, 50 | }); 51 | } catch (err) { 52 | res.send(err); 53 | } 54 | }; 55 | 56 | const getAverageAge = async (req: Request, res: Response) => { 57 | try { 58 | const result = await StudentService.getAverageAge(); 59 | res.send({ 60 | succes: true, 61 | message: "data fetched successfully!", 62 | data: result, 63 | }); 64 | } catch (err) { 65 | res.send(err); 66 | } 67 | }; 68 | 69 | const getStudentEmail = async (req: Request, res: Response) => { 70 | try { 71 | const result = await StudentService.getStudentEmail(); 72 | res.send({ 73 | succes: true, 74 | message: "data fetched successfully!", 75 | data: result, 76 | }); 77 | } catch (err) { 78 | res.send(err); 79 | } 80 | }; 81 | 82 | export const StudentController = { 83 | insertIntoDB, 84 | getStudents, 85 | updateStudentStatus, 86 | getEnrolledStudentName, 87 | getAverageAge, 88 | getStudentEmail, 89 | }; 90 | -------------------------------------------------------------------------------- /src/modules/students/students.service.ts: -------------------------------------------------------------------------------- 1 | import { Prisma, PrismaClient, Student } from "@prisma/client"; 2 | // student service 3 | const prisma = new PrismaClient(); 4 | 5 | const insertIntoDB = async (data: Student): Promise => { 6 | const result = await prisma.student.create({ 7 | data, 8 | }); 9 | return result; 10 | }; 11 | 12 | const updateStudentStatus = async () => { 13 | const highestFrontendNumber = await prisma.student.findFirst({ 14 | orderBy: { 15 | frontend_mark: "desc", 16 | }, 17 | }); 18 | const highestBackendNumber = await prisma.student.findFirst({ 19 | orderBy: { 20 | backend_mark: "desc", 21 | }, 22 | }); 23 | 24 | if (highestFrontendNumber?.student_id && highestBackendNumber?.student_id) { 25 | const result = await prisma.student.update({ 26 | where: { 27 | student_id: highestFrontendNumber.student_id, 28 | }, 29 | data: { 30 | status: "Awarded", 31 | }, 32 | }); 33 | return result; 34 | } 35 | }; 36 | 37 | const getStudents = async () => { 38 | const result = await prisma.student.findMany({ 39 | select: { 40 | student_name: true, 41 | }, 42 | }); 43 | 44 | return result; 45 | }; 46 | 47 | // Retrieve the names of students using a limit of 2, starting from the 3rd student. 48 | const getEnrolledStudentName = async () => { 49 | const result = await prisma.student.findMany({ 50 | select: { 51 | student_name: true, 52 | }, 53 | skip: 2, 54 | take: 2, 55 | }); 56 | return result; 57 | }; 58 | 59 | // Calculate and display the average age of all students. 60 | 61 | const getAverageAge = async () => { 62 | const result = await prisma.student.aggregate({ 63 | _avg: { 64 | age: true, 65 | }, 66 | }); 67 | return { 68 | average_age: result._avg.age, 69 | }; 70 | }; 71 | 72 | // Retrieve the names of students whose email addresses contain 'example.com'. 73 | 74 | const getStudentEmail = async () => { 75 | const result = await prisma.student.findMany({ 76 | where: { 77 | email: { 78 | contains: "example.com", 79 | mode: "insensitive", 80 | }, 81 | }, 82 | select: { 83 | student_name: true, 84 | }, 85 | }); 86 | return result; 87 | }; 88 | 89 | 90 | export const StudentService = { 91 | insertIntoDB, 92 | getStudents, 93 | updateStudentStatus, 94 | getEnrolledStudentName, 95 | getAverageAge, 96 | getStudentEmail, 97 | }; 98 | -------------------------------------------------------------------------------- /PostgreSQL_Assignment.sql: -------------------------------------------------------------------------------- 1 | -- create fresh db 2 | CREATE DATABASE university_db; 3 | 4 | CREATE TABLE students ( 5 | student_id serial PRIMARY KEY, 6 | student_name varchar(255) NOT NULL, 7 | age integer NOT NULL, 8 | email varchar(255) NOT NULL, 9 | frontend_mark integer, 10 | backend_mark integer, 11 | status varchar(255) 12 | ); 13 | 14 | CREATE TABLE courses ( 15 | course_id serial PRIMARY KEY, 16 | course_name varchar(255) NOT NULL, 17 | credits integer NOT NULL 18 | ); 19 | 20 | CREATE TABLE enrollments ( 21 | enrollment_id serial PRIMARY KEY, 22 | student_id integer REFERENCES students (student_id), 23 | course_id integer REFERENCES courses (course_id) 24 | ); 25 | 26 | INSERT INTO students (student_name, age, email, frontend_mark, backend_mark, status) 27 | VALUES 28 | ('Alice', 22, 'alice@example.com', 55, 57, NULL), 29 | ('Bob', 21, 'bob@example.com', 34, 45, NULL), 30 | ('Charlie', 23, 'charlie@example.com', 60, 59, NULL), 31 | ('David', 20, 'david@example.com', 40, 49, NULL), 32 | ('Eve', 24, 'newemail@example.com', 45, 34, NULL), 33 | ('Rahim', 23, 'rahim@gmail.com', 46, 42, NULL); 34 | 35 | INSERT INTO courses (course_name, credits) 36 | VALUES 37 | ('Next.js', 3), 38 | ('React.js', 4), 39 | ('Databases', 3), 40 | ('Prisma', 3); 41 | 42 | INSERT INTO enrollments (student_id, course_id) 43 | VALUES 44 | (1, 1), 45 | (1, 2), 46 | (2, 1), 47 | (3, 2); 48 | 49 | 50 | -- Query 1: Insert a new student record 51 | INSERT INTO students (student_name, age, email, frontend_mark, backend_mark, status) 52 | VALUES 53 | ('siam', 15, 'yourname@c.com', 50, 89, NULL); 54 | 55 | -- Query 2: Retrieve the names of all students who are enrolled in the course titled 'Next.js' 56 | SELECT student_name 57 | FROM students 58 | JOIN enrollments ON students.student_id = enrollments.student_id 59 | WHERE enrollments.course_id IN ( 60 | SELECT course_id 61 | FROM courses 62 | WHERE course_name = 'Next.js' 63 | ); 64 | 65 | -- Query 3: Update the status of the student with the highest total (frontend_mark + backend_mark) mark to 'Awarded' 66 | UPDATE students 67 | SET status = 'Awarded' 68 | WHERE student_id = ( 69 | SELECT student_id 70 | FROM students 71 | ORDER BY frontend_mark + backend_mark DESC 72 | LIMIT 1 73 | ); 74 | 75 | -- Query 4: Delete all courses that have no students enrolled. 76 | DELETE FROM courses 77 | WHERE course_id NOT IN ( 78 | SELECT course_id 79 | FROM enrollments 80 | ); 81 | 82 | -- Query 5: Retrieve the names of students using a limit of 2, starting from the 3rd student. 83 | SELECT student_name 84 | FROM students 85 | ORDER BY student_id 86 | OFFSET 2 87 | LIMIT 2; 88 | 89 | -- Query 6: Retrieve the course names and the number of students enrolled in each course. 90 | SELECT course_id, COUNT(*) AS students_enrolled 91 | FROM enrollments 92 | GROUP BY course_id; 93 | 94 | -- Query 7: Calculate and display the average age of all students. 95 | SELECT AVG(age) AS average_age 96 | FROM students; 97 | 98 | -- Query 8: Retrieve the names of students whose email addresses contain 'example.com'. 99 | SELECT student_name 100 | FROM students 101 | WHERE email LIKE '%example.com'; 102 | -- postgress sql -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 🐞 Hazrat Ali 2 | 3 | # 🪂 Programmer || Software Engineering 4 | 5 | 6 | ## What is PostgreSQL? 7 | 8 | PostgreSQL is an open-source object-relational database management system (ORDBMS) with an emphasis on extensibility and standards compliance. As a database server, its primary function is to store data securely, supporting best practices, and to allow for retrieval at the request of other software applications. It can handle workloads ranging from small single-machine applications to large Internet-facing applications with many concurrent users. 9 | 10 | ## What is the purpose of a database schema in PostgreSQL? 11 | 12 | A database schema is a way to logically group objects such as tables, views, stored procedures, etc. Think of a schema as a container of objects. You can assign a user login permissions to a single schema so that the user can only access the objects they are authorized to access. 13 | 14 | ## Explain the primary key and foreign key concepts in PostgreSQL. 15 | 16 | A primary key is a column or a set of columns that uniquely identifies each row in the table. A table can have only one primary key that consists of single or multiple columns. When multiple columns are used as a primary key, they are called a composite key. 17 | 18 | A foreign key is a column or a set of columns in a table that references to the primary key columns in another table. The table that the foreign key points to is called the referenced table or parent table. A table can have multiple foreign keys depending on its relationships with other tables. 19 | 20 | ## What is the difference between the VARCHAR and CHAR data types? 21 | 22 | The VARCHAR and CHAR are the character data types. The VARCHAR data type is used to store variable-length character strings. The CHAR data type is used to store fixed-length character strings. 23 | 24 | ## Explain the purpose of the WHERE clause in a SELECT statement. 25 | 26 | The WHERE clause is used to filter records. The WHERE clause is used to extract only those records that fulfill a specified condition. 27 | 28 | ## What are the LIMIT and OFFSET clauses used for? 29 | 30 | The LIMIT clause is used to limit the number of rows returned in a query result. The OFFSET clause is used to offset the starting point returned by the LIMIT clause. 31 | 32 | ## How can you perform data modification using UPDATE statements? 33 | 34 | The UPDATE statement is used to modify the existing records in a table. The WHERE clause is used to specify the conditions that identify which rows to modify. 35 | 36 | ## What is the significance of the JOIN operation, and how does it work in PostgreSQL? 37 | 38 | The JOIN operation is used to combine rows from two or more tables based on a related column between them. The JOIN operation is performed whenever two or more tables are joined in a SQL statement. 39 | 40 | ## Explain the GROUP BY clause and its role in aggregation operations. 41 | 42 | The GROUP BY clause is used to group the result set based on one or more columns. The GROUP BY clause is often used with aggregate functions such as SUM, AVG, MAX, MIN, and COUNT. 43 | 44 | ## How can you calculate aggregate functions like COUNT, SUM, and AVG in PostgreSQL? 45 | 46 | The aggregate functions are used to perform calculations on a set of values and return a single value. The aggregate functions are COUNT, SUM, AVG, MAX, and MIN. 47 | 48 | ## What is the purpose of an index in PostgreSQL, and how does it optimize query performance? 49 | 50 | An index is a database structure that is used to speed up the retrieval of rows from the table or view. An index contains keys built from one or more columns in the table or view. These keys are stored in a structure (B-tree) that enables SQL Server to find the row or rows associated with the key values quickly and efficiently. 51 | 52 | ## Explain the concept of a PostgreSQL view and how it differs from a table. 53 | 54 | A view is a virtual table that consists of a subset of data contained in a table. A view can contain all rows of a table or select rows from one or more tables. A view can be created from one or many tables which depends on the written PostgreSQL query to create a view. Views, which are kind of virtual tables, allow users to do the following: 55 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | "rootDir": "./src", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 42 | // "resolveJsonModule": true, /* Enable importing .json files. */ 43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 45 | 46 | /* JavaScript Support */ 47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 50 | 51 | /* Emit */ 52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 58 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 59 | // "removeComments": true, /* Disable emitting comments. */ 60 | // "noEmit": true, /* Disable emitting files from a compilation. */ 61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 68 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 75 | 76 | /* Interop Constraints */ 77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 83 | 84 | /* Type Checking */ 85 | "strict": true, /* Enable all strict type-checking options. */ 86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 104 | 105 | /* Completeness */ 106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 108 | } 109 | } 110 | 111 | // Ts config --------------------------------------------------------------------------------