-
Notifications
You must be signed in to change notification settings - Fork 0
Dev #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AbualiYousef
wants to merge
21
commits into
main
Choose a base branch
from
dev
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Dev #1
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
a8a1f52
Add E-R Diagram
AbualiYousef 57019d9
Add relational schema
AbualiYousef f53a6fa
Add tables creation script
AbualiYousef ab346a6
Add tables seeding scripts
AbualiYousef 44553e9
Add 'List of Borrowed Books' solution script
AbualiYousef b06713e
Add 'List of Borrowed Books' solution script
AbualiYousef d960a2c
Add 'Borrowing Frequency using Window Function' solution script
AbualiYousef 747f353
Add 'Popular Genre Analysis using Joins and Window Functions' solutio…
AbualiYousef 83cb750
Add 'Stored Procedure - Add New Borrowers' solution script
AbualiYousef 5f67f03
Add 'Database Function - Calculate Overdue Fees' solution script
AbualiYousef 81ccc98
Add 'Database Function - Book Borrowing Frequency' solution script
AbualiYousef 53dea28
Add 'Overdue Analysis' solution script
AbualiYousef d71e166
Add 'Author Popularity using Aggregation' solution script
AbualiYousef 72e4a2f
Add 'Genre Preference by Age using Group By and Having' solution script
AbualiYousef c601fc5
Add 'Stored Procedure - Borrowed Books Report' solution script
AbualiYousef 09cf8e4
Add 'Trigger Implementation' solution script
AbualiYousef 6ee9161
Add 'SQL Stored Procedure with Temp Table' solution script
AbualiYousef 14119ac
Add 'BONUS - Weekly Peaks Days' solution script
AbualiYousef 8dfd03a
Update README.md
AbualiYousef 70f4780
Rename seeding scripts
AbualiYousef 766e8e1
Update multiple procedures using CREATE OR ALTER
AbualiYousef File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,76 @@ | ||
# Library-Management-System-Database | ||
# Library Management System: Database Project | ||
|
||
## Background | ||
|
||
A local library is transitioning from traditional book-keeping to a digital system. The aim is to efficiently track books, borrowers, loans, returns, and provide insights into borrowing trends. | ||
|
||
## Objective | ||
|
||
Design and implement a relational database using MS SQL to support the library's operations and enhance querying capabilities. | ||
|
||
## Requirements | ||
|
||
### 1. Design an Entity Relationship Model (ERM) Diagram | ||
|
||
- **Entities**: Books, Borrowers, and Loans. | ||
- **Attributes**: Specify attributes for each entity. | ||
- **Relationships**: Show connections between entities. | ||
- **Connectivity and Cardinality**: Indicate relationship types. | ||
- **Keys**: Identify primary (PK). | ||
- **Tools**: Use ERDPlus, Lucidchart, or similar. | ||
|
||
 | ||
|
||
### 2. Design the Relational Schema using MS SQL | ||
|
||
- **Books**: | ||
- BookID (PK) | ||
- Title | ||
- Author | ||
- ISBN | ||
- Published Date | ||
- Genre | ||
- Shelf Location | ||
- Current Status ('Available' or 'Borrowed') | ||
|
||
- **Borrowers**: | ||
- BorrowerID (PK) | ||
- First Name | ||
- Last Name | ||
- Date of Birth | ||
- Membership Date | ||
|
||
- **Loans**: | ||
- LoanID (PK) | ||
- BookID (FK) | ||
- BorrowerID (FK) | ||
- Date Borrowed | ||
- Due Date | ||
- Date Returned (NULL if not returned yet) | ||
|
||
 | ||
|
||
### 3. Build and Seed the Database | ||
|
||
- Construct the database in MS SQL. | ||
- Seed with 1000 books, 1000 borrowers, and 1000 loans. Include DML scripts for seeding in the repository. | ||
|
||
### 4. Complex Queries and Procedures | ||
|
||
- **List of Borrowed Books**: Query to retrieve all borrowed books for a specific borrower. | ||
- **Active Borrowers with CTEs**: Identify borrowers with 2+ borrowed books not yet returned. | ||
- **Borrowing Frequency using Window Functions**: Rank borrowers based on frequency. | ||
- **Popular Genre Analysis**: Determine the most popular genre per month. | ||
- **Stored Procedure - `sp_AddNewBorrower`**: Add a new borrower; handle existing emails. | ||
- **Database Function - `fn_CalculateOverdueFees`**: Compute overdue fees for loans. | ||
- **Database Function - `fn_BookBorrowingFrequency`**: Count how many times a book has been borrowed. | ||
- **Overdue Analysis**: List overdue books with associated borrowers. | ||
- **Author Popularity using Aggregation**: Rank authors by borrowing frequency. | ||
- **Genre Preference by Age**: Determine genre preference across age groups. | ||
- **Stored Procedure - `sp_BorrowedBooksReport`**: Generate a report of books borrowed within a date range. | ||
- **Trigger Implementation**: Log changes in book status to an `AuditLog`. | ||
|
||
### BONUS | ||
|
||
- **Weekly Peak Days**: Identify the three busiest days of the week for loans and express as a percentage of total loans. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--1. List of Borrowed Books: Retrieve all books borrowed by a specific borrower, including those currently unreturned. | ||
|
||
declare @BorrowerId int = 7; | ||
SELECT Books.title, Books.author, Loans.dateBorrowed, Loans.dueDate | ||
FROM Loans | ||
JOIN Books ON Loans.bookId = Books.bookId | ||
WHERE Loans.borrowerId = @BorrowerId; |
52 changes: 52 additions & 0 deletions
52
complexQueriesAndProcedures/10.GenrePreferenceByAgeUsingGroupByAndHaving.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
--10.Genre Preference by Age using Group By and Having: | ||
WITH BorrowerAges AS ( | ||
SELECT | ||
borrowerId, | ||
(DATEDIFF(YEAR, dateOfBirth, GETDATE()) / 10) * 10 AS AgeBracket | ||
FROM | ||
Borrowers | ||
), | ||
LoanGenres AS ( | ||
SELECT | ||
ba.AgeBracket, | ||
b.genre, | ||
COUNT(*) AS GenreCount | ||
FROM | ||
BorrowerAges ba | ||
JOIN Loans l ON ba.borrowerId = l.borrowerId | ||
JOIN Books b ON l.bookId = b.bookId | ||
GROUP BY | ||
ba.AgeBracket, | ||
b.genre | ||
), | ||
RankedGenres AS ( | ||
SELECT | ||
AgeBracket, | ||
genre, | ||
GenreCount, | ||
ROW_NUMBER() OVER ( | ||
PARTITION BY AgeBracket | ||
ORDER BY GenreCount DESC, genre ASC | ||
) AS RowNum | ||
FROM | ||
LoanGenres | ||
) | ||
SELECT | ||
CASE | ||
WHEN AgeBracket = 0 THEN '0-10' | ||
WHEN AgeBracket = 10 THEN '11-20' | ||
WHEN AgeBracket = 20 THEN '21-30' | ||
WHEN AgeBracket = 30 THEN '31-40' | ||
WHEN AgeBracket = 40 THEN '41-50' | ||
WHEN AgeBracket = 50 THEN '51-60' | ||
WHEN AgeBracket >= 60 THEN '61+' | ||
ELSE 'Unknown' | ||
END AS AgeGroup, | ||
genre, | ||
GenreCount | ||
FROM | ||
RankedGenres | ||
WHERE | ||
RowNum = 1 | ||
ORDER BY | ||
AgeBracket; |
26 changes: 26 additions & 0 deletions
26
complexQueriesAndProcedures/11.StoredProcedure-BorrowedBooksReport.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--11.Stored Procedure - Borrowed Books Report: | ||
CREATE OR ALTER PROCEDURE PROCEDURE sp_BorrowedBooksReport | ||
@StartDate DATE, | ||
@EndDate DATE | ||
AS | ||
BEGIN | ||
-- Query to retrieve borrowed book details within the specified date range | ||
SELECT | ||
b.title AS BookTitle, | ||
b.author AS Author, | ||
br.firstName + ' ' + br.lastName AS BorrowerName, | ||
l.dateBorrowed AS BorrowingDate | ||
FROM | ||
Loans l | ||
INNER JOIN Books b ON l.bookId = b.bookId | ||
INNER JOIN Borrowers br ON l.borrowerId = br.borrowerId | ||
WHERE | ||
l.dateBorrowed BETWEEN @StartDate AND @EndDate | ||
ORDER BY | ||
BorrowingDate ASC; | ||
END; | ||
|
||
--Test the sp | ||
EXEC sp_BorrowedBooksReport | ||
@StartDate = '2024-01-01', | ||
@EndDate = '2024-01-17'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--12.Trigger Implementation | ||
DROP TRIGGER IF EXISTS trg_BookStatusChange; | ||
GO | ||
CREATE TRIGGER trg_BookStatusChange ON Books | ||
AFTER UPDATE | ||
AS | ||
BEGIN | ||
DECLARE @BookID INT; | ||
DECLARE @OldStatus VARCHAR(50); | ||
DECLARE @NewStatus VARCHAR(50); | ||
DECLARE @StatusChange VARCHAR(100); | ||
IF UPDATE(currentStatus) | ||
BEGIN | ||
SELECT @BookID = i.bookId, @OldStatus = d.currentStatus, @NewStatus = i.currentStatus | ||
FROM inserted i | ||
JOIN deleted d ON i.bookId = d.bookId; | ||
|
||
IF (@OldStatus <> @NewStatus) | ||
BEGIN | ||
SET @StatusChange = 'Status changed from ' + @OldStatus + ' to ' + @NewStatus; | ||
INSERT INTO AuditLog | ||
VALUES (@BookID, @StatusChange, GETDATE()); | ||
END | ||
END | ||
END; | ||
|
||
-- Example to update a book's status to 'Borrowed' | ||
UPDATE Books | ||
SET currentStatus = 'Borrowed' | ||
WHERE bookId = 1 AND currentStatus = 'Available'; | ||
|
||
-- Example to update a book's status to 'Available' | ||
UPDATE Books | ||
SET currentStatus = 'Available' | ||
WHERE bookId = 1 AND currentStatus = 'Borrowed'; | ||
|
||
-- Check the AuditLog: | ||
SELECT * FROM AuditLog; |
36 changes: 36 additions & 0 deletions
36
complexQueriesAndProcedures/14.SQLStoredProcedureWithTempTable.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
-- 14.SQL Stored Procedure with Temp Table: | ||
DROP PROCEDURE IF EXISTS sp_GetOverdueBooksByBorrower; | ||
GO | ||
CREATE PROCEDURE sp_GetOverdueBooksByBorrower | ||
AS | ||
BEGIN | ||
-- Create a temporary table | ||
CREATE TABLE #OverdueBorrowers ( | ||
borrowerId INT | ||
); | ||
|
||
-- Insert borrowers who have overdue books into the temporary table: | ||
INSERT INTO #OverdueBorrowers (borrowerId) | ||
SELECT DISTINCT l.borrowerId | ||
FROM Loans l | ||
WHERE l.dateReturned IS NULL AND l.dueDate < GETDATE(); | ||
|
||
-- Select the overdue books for each borrower by joining the temp table with the Loans table | ||
SELECT | ||
br.borrowerId, | ||
br.firstName + ' ' + br.lastName AS BorrowerName, | ||
b.bookId, | ||
b.title AS BookTitle, | ||
l.dueDate AS DueDate | ||
FROM #OverdueBorrowers obr | ||
JOIN Loans l ON obr.borrowerId = l.borrowerId | ||
JOIN Borrowers br ON obr.borrowerId = br.borrowerId -- Make sure to join Borrowers here | ||
JOIN Books b ON l.bookId = b.bookId | ||
WHERE l.dateReturned IS NULL AND l.dueDate < GETDATE(); | ||
|
||
-- Drop the temporary table | ||
DROP TABLE #OverdueBorrowers; | ||
END; | ||
|
||
-- Test the sp: | ||
EXEC sp_GetOverdueBooksByBorrower; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--2.Active Borrowers with CTEs: | ||
WITH ActiveBorrowers AS ( | ||
SELECT borrowerId, COUNT(*) AS TotalLoans | ||
FROM Loans | ||
WHERE dateReturned IS NULL | ||
GROUP BY borrowerId | ||
HAVING COUNT(*) >= 2 | ||
) | ||
SELECT Borrowers.*, ActiveBorrowers.TotalLoans | ||
FROM ActiveBorrowers | ||
JOIN Borrowers ON ActiveBorrowers.borrowerId = Borrowers.borrowerId; |
6 changes: 6 additions & 0 deletions
6
complexQueriesAndProcedures/3.BorrowingFrequencyUsingWindowFunctions.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--3.Borrowing Frequency using Window Functions: | ||
SELECT Borrowers.borrowerId, Borrowers.firstName, Borrowers.lastName, COUNT(Loans.borrowerId) AS TotalLoans, | ||
RANK() OVER (ORDER BY COUNT(Loans.borrowerId) DESC) AS BorrowerRank | ||
FROM Borrowers | ||
LEFT JOIN Borrowers ON Loans.borrowerId = Borrowers.borrowerId | ||
GROUP BY Borrowers.borrowerId, Borrowers.firstName, Borrowers.lastName; |
9 changes: 9 additions & 0 deletions
9
complexQueriesAndProcedures/4.PopularGenreAnalysisUsingJoinsAndWindowFunction.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--4.Popular Genre Analysis using Joins and Window Functions: | ||
DECLARE @Month INT=4; | ||
DECLARE @Year INT=2022; | ||
SELECT genre, COUNT(*) AS TotalLoans, | ||
RANK() OVER (ORDER BY COUNT(*) DESC) AS GenreRank | ||
FROM Loans | ||
JOIN Books ON Loans.bookId = Books.bookId | ||
WHERE MONTH(dateBorrowed) = @Month AND YEAR(dateBorrowed) = @Year | ||
GROUP BY genre; |
28 changes: 28 additions & 0 deletions
28
complexQueriesAndProcedures/5.StoredProcedure-AddNewBorrowers.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--5.Stored Procedure - Add New Borrowers: | ||
CREATE OR ALTER PROCEDURE PROCEDURE sp_AddNewBorrower | ||
@FirstName VARCHAR(255), | ||
@LastName VARCHAR(255), | ||
@Email VARCHAR(255), | ||
@DateOfBirth DATE, | ||
@MembershipDate DATE | ||
AS | ||
BEGIN | ||
IF EXISTS (SELECT Borrowers.borrowerId FROM Borrowers WHERE email = @Email) | ||
BEGIN | ||
SELECT 'Error: A borrower with this email already exists.' AS ErrorMessage; | ||
END | ||
ELSE | ||
BEGIN | ||
INSERT INTO Borrowers | ||
VALUES (@FirstName, @LastName, @Email, @DateOfBirth, @MembershipDate); | ||
SELECT SCOPE_IDENTITY() AS NewBorrowerID; | ||
END | ||
END; | ||
|
||
-- Test the procedure by executing it | ||
EXEC sp_AddNewBorrower | ||
@FirstName = 'John', | ||
@LastName = 'Doe', | ||
@Email = 'john.doe@example.com', | ||
@DateOfBirth = '1990-05-15', | ||
@MembershipDate = '2023-04-15'; |
40 changes: 40 additions & 0 deletions
40
complexQueriesAndProcedures/6.DatabaseFunction-CalculateOverdueFees.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
--6.Database Function - Calculate Overdue Fees | ||
drop function if exists fn_CalculateOverdueFees; | ||
go | ||
CREATE FUNCTION fn_CalculateOverdueFees (@LoanID INT) | ||
RETURNS MONEY | ||
AS | ||
BEGIN | ||
DECLARE @DateBorrowed DATE; | ||
DECLARE @DueDate DATE; | ||
DECLARE @DateReturned DATE; | ||
DECLARE @OverdueDays INT; | ||
DECLARE @OverdueFee MONEY = 0; | ||
|
||
-- Retrieve loan dates | ||
SELECT @DateBorrowed = dateBorrowed, @DueDate = dueDate, @DateReturned = dateReturned | ||
FROM Loans | ||
WHERE loanId = @LoanID; | ||
|
||
-- Calculate overdue days | ||
IF @DateReturned IS NULL | ||
SET @DateReturned = GETDATE(); | ||
|
||
SET @OverdueDays = DATEDIFF(DAY, @DueDate, @DateReturned); | ||
|
||
-- Calculate fees based on the overdue days | ||
IF @OverdueDays > 0 | ||
BEGIN | ||
IF @OverdueDays <= 30 | ||
SET @OverdueFee = @OverdueDays * 1.00; | ||
ELSE | ||
SET @OverdueFee = (30 * 1.00) + ((@OverdueDays - 30) * 2.00); | ||
END | ||
|
||
RETURN @OverdueFee; | ||
END; | ||
|
||
|
||
|
||
--Test the function: | ||
SELECT dbo.fn_CalculateOverdueFees(1) AS OverdueFee; |
15 changes: 15 additions & 0 deletions
15
complexQueriesAndProcedures/7.DatabaseFunction-BookBorrowingFrequency.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--7.Database Function - Book Borrowing Frequency: | ||
|
||
CREATE FUNCTION fn_BookBorrowingFrequency (@BookID INT) | ||
RETURNS INT | ||
AS | ||
BEGIN | ||
RETURN( | ||
SELECT COUNT(*) | ||
FROM Loans | ||
WHERE bookId = @BookID | ||
); | ||
END; | ||
|
||
|
||
SELECT dbo.fn_BookBorrowingFrequency(1) AS BorrowingFrequency; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--8.Overdue Analysis: List all books overdue by more than 30 days with their associated borrowers. | ||
|
||
SELECT b.*,bo.*, | ||
DATEDIFF(DAY, l.dueDate, GETDATE()) AS DaysOverdue | ||
FROM | ||
Loans l | ||
JOIN Books b ON l.bookId = b.bookId | ||
JOIN Borrowers bo ON l.borrowerId = bo.borrowerId | ||
WHERE | ||
l.dateReturned IS NULL AND | ||
DATEDIFF(DAY, l.dueDate, GETDATE()) > 30; |
11 changes: 11 additions & 0 deletions
11
complexQueriesAndProcedures/9.AuthorPopularityUsingAggregation.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--9.Author Popularity using Aggregation: | ||
|
||
SELECT | ||
b.author, | ||
COUNT(l.loanId) AS BorrowingCount, | ||
RANK() OVER (ORDER BY COUNT(l.loanId) DESC) AS AuthorRank | ||
FROM | ||
Books b | ||
LEFT JOIN Loans l ON b.bookId = l.bookId | ||
GROUP BY | ||
b.author |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just care that you are aware RANK() OVER is not aggregation its window func