Homework - OnlineShop
Phần A: Tạo bảng
- Viết các câu lệnh tạo bảng như phần mô tả CSDL OnlineShop
- Tạo mỗi bảng từ 5-10 records: Sử dụng câu lệnh INSERT, thứ tự nhập dữ liệu cho các tables:
- Categories
- Suppliers
- Customers
- Employees
- Products
- Orders
- OrderDetails
Phần B: Câu lệnh INSERT, UPDATE, DELETE
- Viết câu lệnh UPDATE để cập nhật Price với điều kiện: Các mặt hàng có
Price <= 100000
thì tăng thêm 10% - Viết câu lệnh UPDATE để cập nhật DISCOUNT với điều kiện: Các mặt hàng có
Discount <= 10%
thì tăng thêm 5% - Viết câu lệnh XOÁ tất cả các mặt hàng có Stock là 0
Phần C: Truy vấn cơ bản
- Hiển thị tất cả các mặt hàng có giảm giá
<= 10%
- Hiện thị tất cả các mặt hàng không có giảm giá
- Hiển thị tất cả các mặt hàng có số lượng tồn kho
<= 5
- Hiển thị tất cả các mặt hàng có Giá bán sau khi đã giảm giá
<= 100.000
- Hiện thị tất cả các mặt hàng thuộc danh mục CPU, RAM
- Hiển thị tất cả các khách hàng có địa chỉ ở
Quận Hải Châu
- Hiển thị tất cả các khách hàng có địa chỉ ở Quận Hải Châu hoặc Quận Thanh Khê
- Hiển thị tất cả các khách hàng có năm sinh
1990
. - Hiển thị tất cả các khách hàng có tuổi trên
60
. - Hiển thị tất cả các khách hàng có tuổi
từ 20 đến 30
. - Hiển thị tất cả các khách hàng có sinh nhật là hôm nay. Gợi ý:
dùng hàm GETDATE(), MONTH(), DAY()
- Hiển thị tất cả các đơn hàng có trạng thái là
COMPLETED
- Hiển thị tất cả các đơn hàng có trạng thái là
COMPLETED
trongngày hôm nay
- Hiển thị tất cả các đơn hàng chưa hoàn thành trong
tháng này
- Hiển thị tất cả các đơn hàng có trạng thái là
CANCELED
- Hiển thị tất cả các đơn hàng có trạng thái là
CANCELED
trongngày hôm nay
- Hiển thị tất cả các đơn hàng có trạng thái là
COMPLETED
trongtháng này
- Hiển thị tất cả các đơn hàng có trạng thái là
COMPLETED
trongtháng 1 năm 2021
- Hiển thị tất cả các đơn hàng có trạng thái là
COMPLETED
trongnăm 2021
- Hiển thị tất cả các đơn hàng có hình thức thanh toán là
CASH
- Hiển thị tất cả các đơn hàng có hình thức thanh toán là
CREADIT CARD
- Hiển thị tất cả các đơn hàng có địa chỉ giao hàng là
Hà Nội
- Hiển thị tất cả các nhân viên có sinh nhật là
tháng này
- Hiển thị tất cả các nhà cung cấp có tên là:
(SONY, SAMSUNG, TOSHIBA, APPLE)
- Hiển thị tất cả các nhà cung cấp không có tên là:
(SAMSUNG, APPLE)
- Hiển thị tất cả các nhà cung cấp có địa chỉ ở Quận Hải Châu và Quận Thanh Khê.
- Hiển thị tất cả các nhà cung cấp có địa chỉ ở Quận Hải Châu hoặc Quận Thanh Khê.
- Hiển thị tất cả các khách hàng có sinh nhật là
ngày hôm nay
. - Hiển thị xem có bao nhiêu mức giảm giá khác nhau.
- Hiển thị xem có bao nhiêu mức giảm giá khác nhau và số lượng mặt hàng có mức giảm giá đó.
- Hiển thị xem có bao nhiêu mức giảm giá khác nhau và số lượng mặt hàng có mức giảm giá đó, sắp xếp theo số lượng giảm giá giảm dần.
- Hiển thị xem có bao nhiêu mức giảm giá khác nhau và số lượng mặt hàng có mức giảm giá đó, sắp xếp theo số lượng giảm giá tăng dần, chỉ hiển thị các mức giảm gi á có số lượng mặt hàng >= 5
- Hiển thị xem có bao nhiêu mức tuổi khác nhau của khách hàng và số lượng khách hàng có mức tuổi đó, sắp xếp theo số lượng khách hàng tăng dần.
- Hiển thị xem có bao nhiêu mức tuổi khác nhau của nhân viên và số lượng nhân viên có mức tuổi đó, sắp xếp theo số lượng nhân viên giảm dần.
- Hiển thị số lượng đơn hàng theo từng ngày khác nhau sắp xếp theo số lượng đơn hàng giảm dần.
- Hiển thị số lượng đơn hàng theo từng tháng khác nhau sắp xếp theo số lượng đơn hàng giảm dần.
- Hiển thị số lượng đơn hàng theo từng năm khác nhau sắp xếp theo số lượng đơn hàng giảm dần.
- Hiển thị số lượng đơn hàng theo từng năm khác nhau sắp xếp theo số lượng đơn hàng giảm dần, chỉ hiển thị các năm có số lượng đơn hàng
>= 5
.
Phần D: Truy vấn nâng cao
- Hiển thị tất cả các mặt hàng cùng với CategoryName.
SELECT ProductName, CategoryName
FROM Products
INNER JOIN Categories ON Products.CategoryId = Categories.Id
- Hiển thị tất cả các mặt hàng cùng với SupplierName.
SELECT ProductName, SupplierName
FROM Products
INNER JOIN Suppliers ON Products.SupplierId = Suppliers.Id
- Hiển thị tất cả các mặt hàng cùng với thông tin chi tiết của Category và Supplier.
SELECT ProductName, CategoryName, SupplierName
FROM Products
INNER JOIN Categories ON Products.CategoryId = Categories.Id
INNER JOIN Suppliers ON Products.SupplierId = Suppliers.Id
- Hiển thị tất cả các đơn hàng cùng với thông tin chi tiết khách hàng Customer.
- Hiển thị tất cả các đơn hàng cùng với thông tin chi tiết nhân viên Employee.
- Hiển thị tất cả các đơn hàng cùng với thông tin chi tiết khách hàng Customer và nhân viên Employee.
- Hiển thị tất cả danh mục (Categories) với số lượng hàng hóa trong mỗi danh mục
- Dùng
INNER JOIN
+GROUP BY
với lệnh COUNT - Dùng SubQuery với lệnh COUNT
- Dùng
- Hiển thị tất cả nhà cung cấp (Suppliers) với số lượng hàng hóa mỗi nhà cung cấp
- Dùng INNER JOIN + GROUP BY với lệnh COUNT
- Dùng SubQuery với lệnh COUNT
- Hiển thị tất cả các mặt hàng được bán trong khoảng từ ngày, đến ngày
- Hiển thị tất cả các khách hàng mua hàng trong khoảng từ ngày, đến ngày
- Hiển thị tất cả các khách hàng mua hàng (với tổng số tiền) trong khoảng từ ngày, đến ngày
- Dùng INNER JOIN + GROUP BY với lệnh SUM
- Dùng SubQuery với lệnh SUM
- Hiển thị tất cả đơn hàng với tổng số tiền của đơn hàng đó
- Hiển thị tất cả các nhân viên bán hàng với tổng số tiền bán được
- Hiển thị tất cả các mặt hàng không bán được
- Hiển thị tất cả các nhà cung cấp không bán được trong khoảng từ ngày, đến ngày
- Hiển thị top 3 các nhân viên bán hàng với tổng số tiền bán được từ cao đến thấp trong khoảng từ ngày, đến ngày
- Hiển thị top 5 các khách hàng mua hàng với tổng số tiền mua được từ cao đến thấp trong khoảng từ ngày, đến ngày
- Hiển thị danh sách các mức giảm giá của cửa hàng
- Hiển thị tất cả danh mục (Categories) với tổng số tiền bán được trong mỗi danh mục
- Dùng INNER JOIN + GROUP BY với lệnh SUM
- Dùng SubQuery với lệnh SUM
- Hiển thị tất cả đơn hàng với tổng số tiền mà đã được giao hàng thành công trong khoảng từ ngày, đến ngày
- Hiển thị tất cả đơn hàng có tổng số tiền bán hàng nhiều nhất trong khoảng từ ngày, đến ngày
- Hiển thị tất cả đơn hàng có tổng số tiền bán hàng ít nhất trong khoảng từ ngày, đến ngày
- Hiển thị trung bình cộng giá trị các đơn hàng trong khoảng từ ngày, đến ngày
- Hiển thị các đơn hàng có giá trị cao nhất
- Hiển thị các đơn hàng có giá trị thấp nhất
Phần E: Views
- Hiển thị danh sách các mức giảm giá của cửa hàng cùng với số lượng mặt hàng được giảm giá đó, gồm các fields: Discount, NumberOfProducts, Total.
- Hiển thị tất cả các mặt hàng cùng với thông tin chi tiết của Category và Supplier gồm các fields: Id, Name, Price, Discount, CategoryId, CategoryName, SupplierId, SupplierName.
- Hiển thị tất cả các đơn hàng cùng với thông tin chi tiết khách hàng Customer và Employee gồm các fields: Id, OrderDate, Status, CustomerId, CustomerName, CustomerAddress, CustomerPhone, EmployeeId, EmployeeName, EmployeeAddress, EmployeePhone, Total.
- Hiển thị tất cả danh mục (Categories) với số lượng hàng hóa trong mỗi danh mục, gồm các fields: Id, Name, Description, NumberOfProducts.
- Dùng INNER JOIN + GROUP BY với lệnh COUNT
- Dùng SubQuery với lệnh COUNT
- Hiển thị tất cả nhà cung cấp (Suppliers) với số lượng hàng hóa mỗi nhà cung cấp, gồm các fields: Id, Name, Address, PhoneNumber, NumberOfProducts.
- Dùng INNER JOIN + GROUP BY với lệnh COUNT
- Dùng SubQuery với lệnh COUNT
- Hiển thị tất cả các khách hàng mua hàng với tổng số tiền mua hàng, gồm các fields: Id, Name, Address, PhoneNumber, Total.
- Dùng INNER JOIN + GROUP BY với lệnh SUM
- Dùng SubQuery với lệnh SUM
CREATE VIEW v_CustomersWithTotal
AS
SELECT
O.CustomerId,
C.FirstName + ' ' + C.LastName AS [FullName],
C.PhoneNumber,
C.Address,
SUM((OD.Price * (100 - OD.Discount) / 100) * OD.Quantity) AS [Total]
FROM
Orders AS O
INNER JOIN OrderDetails AS OD ON O.Id = OD.OrderId
INNER JOIN Customers AS C ON O.CustomerId = C.Id
GROUP BY
O.CustomerId,
C.FirstName + ' ' + C.LastName,
C.PhoneNumber,
C.Address
Dùng Sub Query
CREATE VIEW v_CustomersWithTotal
AS
SELECT V.*
FROM
(
SELECT
DISTINCT
C.Id,
C.FirstName + ' ' + C.LastName AS [FullName],
C.PhoneNumber,
C.Address,
(
SELECT SUM((OD.Price * (100 - OD.Discount) / 100) * OD.Quantity)
FROM OrderDetails AS OD
INNER JOIN Orders AS O ON OD.OrderId = O.Id
WHERE O.CustomerId = C.Id
) AS [Total]
FROM
Customers AS C
) AS V
WHERE V.Total IS NOT NULL
- Hiển thị tất cả các nhân viên bán hàng với tổng số tiền bán được, gồm các fields: Id, Name, Address, PhoneNumber, Total.
- Dùng INNER JOIN + GROUP BY với lệnh SUM
- Dùng SubQuery với lệnh SUM
- Hiển thị tất cả các mặt hàng không bán được, gồm các fields: Id, Name, Price, Discount, CategoryId, CategoryName, SupplierId, SupplierName.
CREATE VIEW v_Products_NotSold
AS
SELECT
P.*, C.Name AS 'CategoryName', S.Name AS 'SupplierName'
FROM Products AS P
INNER JOIN Categories AS C ON P.CategoryId = C.Id
INNER JOIN Suppliers AS S ON P.SupplierId = S.Id
WHERE NOT EXISTS (
SELECT P.Id FROM OrderDetails AS OD WHERE P.Id = OD.ProductId
)
- Hiển thị tất cả các nhà cung cấp không bán được, gồm các fields: Id, Name, Address, PhoneNumber.
- Hiển thị tất cả các nhân viên không bán được hàng, gồm các fields: Id, Name, Address, PhoneNumber.
CREATE VIEW v_Employess_NotSellProducts
AS
SELECT * FROM Employees AS E
WHERE NOT EXISTS (
SELECT O.EmployeeId FROM Orders AS O WHERE E.Id = O.EmployeeId
)
Phần F: Stored Procedures
- Hiển thị tất cả các mặt hàng có giảm giá
<= @MinDiscount
- Hiển thị tất cả các mặt hàng có số lượng tồn kho
<= @MinStock
- Hiển thị tất cả các mặt hàng có Giá bán sau khi đã giảm giá
<= @Total
- Hiển thị tất cả các khách hàng có địa chỉ ở
@Address
- Hiển thị tất cả các khách hàng có năm sinh
@YearOfBirth
- Hiển thị tất cả các khách hàng có tuổi
từ @MinAge đến MaxAge
. - Hiển thị tất cả các khách hàng có sinh nhật là
@Date
- Hiển thị tất cả các đơn hàng có trạng thái là
@Status
trong ngày@Date
- Hiển thị tất cả các đơn hàng chưa hoàn thành trong tháng
@Month
của năm@Year
- Hiển thị tất cả các đơn hàng có hình thức thanh toán là
@PaymentMethod
- Hiển thị tất cả đơn hàng theo trạng thái
@Status
với tổng số tiền của đơn hàng đó trong khoảng từ ngày@FromDate
, đến ngày@ToDate
- Hiển thị tất cả các nhân viên bán hàng theo trạng thái
@Status
với tổng số tiền bán được trong khoảng từ ngày@FromDate
, đến ngày@ToDate
- Hiển thị tất cả các mặt hàng không bán được trong khoảng từ ngày
@FromDate
, đến ngày@ToDate
- Hiển thị tất cả các nhà cung cấp không bán được trong khoảng từ ngày
@FromDate
, đến ngày@ToDate
- Hiển thị tất cả các khách hàng mua hàng với tổng số tiền trong khoảng từ ngày
@FromDate
, đến ngày@ToDate
Phần G: Functions
- Viết 1 scalar function ghép FirstName
@FirstName
và LastName@LastName
, tên function làudf_GetFullName
- Viết 1 scalar funtion tính total price (
@Price
,@Discount
,@Quantity
), tên function làudf_Product_GetTotalPrice
- Viết 1 scalar function tính total price của 1 Order (
@OrderID
), tên function làudf_Order_GetTotalPrice
- Viết table function trả về table gồm các fields: OrderId, ProductId, ProductName, CategoryId, CategoryName, Quantity, Price, Discount, Total với tham số
@OrderId
, tên function làudf_Order_GetOrderDetails
- Viết table function trả về các mức giá của 1 danh mục loại sản phẩm, với tham số
@CategoryId
, tên function làudf_Category_GetCategoryPrices
- Viết table function trả về các mức giảm giá của 1 danh mục loại sản phẩm, với tham số
@CategoryId
, tên function làudf_Category_GetCategoryDiscounts
- Viết scalar function nhập vào năm sinh, trả về số tuổi, tên function là
udf_CalculateAge
- Viết scalar function chuyển đổi UNICODE có dấu sang không dấu, tên function là
udf_ConvertUnicodeToNonUnicode
, ví dụ: udf_ConvertUnicodeToNonUnicode(N'Ngô Thanh Tùng') -> 'Ngo Thanh Tung'.
CREATE OR ALTER FUNCTION [dbo].[udf_ConvertUnicodeToNonUnicode]
(
@Text NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
IF (@Text IS NULL OR @Text = '') RETURN ''
DECLARE @RT NVARCHAR(MAX)
DECLARE @SIGN_CHARS NCHAR(256)
DECLARE @UNSIGN_CHARS NCHAR (256)
SET @SIGN_CHARS = N'ăâđêôơưàảãạáằẳẵặắầẩẫậấèẻẽẹéềểễệếìỉĩịíòỏõọóồổỗộốờởỡợớùủũụúừửữựứỳỷỹỵýĂÂĐÊÔƠƯÀẢÃẠÁẰẲẴẶẮẦẨẪẬẤÈẺẼẸÉỀỂỄỆẾÌỈĨỊÍÒỎÕỌÓỒỔỖỘỐỜỞỠỢỚÙỦŨỤÚỪỬỮỰỨỲỶỸỴÝ' + NCHAR(272) + NCHAR(208)
SET @UNSIGN_CHARS = N'aadeoouaaaaaaaaaaaaaaaeeeeeeeeeeiiiiiooooooooooooooouuuuuuuuuuyyyyyAADEOOUAAAAAAAAAAAAAAAEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOUUUUUUUUUUYYYYYDD'
DECLARE @COUNTER int
DECLARE @COUNTER1 int
SET @COUNTER = 1
WHILE (@COUNTER <= LEN(@Text))
BEGIN
SET @COUNTER1 = 1
WHILE (@COUNTER1 <= LEN(@SIGN_CHARS) + 1)
BEGIN
IF UNICODE(SUBSTRING(@SIGN_CHARS, @COUNTER1, 1)) = UNICODE(SUBSTRING(@Text,@COUNTER ,1))
BEGIN
IF @COUNTER = 1
SET @Text = SUBSTRING(@UNSIGN_CHARS, @COUNTER1, 1) + SUBSTRING(@Text, @COUNTER + 1, LEN(@Text) - 1)
ELSE
SET @Text = SUBSTRING(@Text, 1, @COUNTER - 1) + SUBSTRING(@UNSIGN_CHARS, @COUNTER1, 1) + SUBSTRING(@Text, @COUNTER + 1, LEN(@Text) - @COUNTER)
BREAK
END
SET @COUNTER1 = @COUNTER1 + 1
END
SET @COUNTER = @COUNTER + 1
END
SET @Text = REPLACE(@Text, '--', '-')
SET @Text = REPLACE(@Text, '--', '-')
SET @Text = REPLACE(@Text, '--', '-')
SET @Text = REPLACE(@Text, '--', '-')
RETURN @Text
END
- Viết scalar function chuyển đổi tên sản phẩm thành SEO Url, tên function là
udf_ConvertToSeoUrl
, ví dụ: udf_ConvertToSeoUrl(N'Điện thoại iPhone 12 Pro Max 256GB') -> 'dien-thoai-iphone-12-pro-max-256gb'.
Phần H: Triggers
- Tạo 1 trigger trên bảng Orders: chặn update bảng Orders khi các Orders có Status = 'COMPLETED' hoặc 'CANCELLED'.
- Tạo 1 trigger trên bảng Orders: chặn delete bảng Orders khi các Orders có Status = 'COMPLETED' hoặc 'CANCELLED'.
- Tạo 1 trigger trên bảng OrderDetails: chặn update bảng OrderDetails khi các Orders có Status = 'COMPLETED' hoặc 'CANCELLED'.
- Tạo 1 trigger trên bảng OrderDetails: chặn delete bảng OrderDetails khi các Orders có Status = 'COMPLETED' hoặc 'CANCELLED'.
- Tạo 1 trigger trên bảng Orders: cập nhật tồn kho (Stock), trừ đi số lượng đã bán (Quantity) khi Orders có Status = 'WAITING', cộng lại số lượng đã bán (Quantity) khi Orders có Status = 'CANCELED'.
- Tạo 1 trigger trên bảng Orders: ghi nhật ký khi Orders được giao hàng thành công (Status = 'COMPLETED'), Ghi vào bảng OrderLogs (Id, OrderId, Status, CreatedDate, EmployeeId, CustomerId)
Phần I: Transactions
- Tạo store procedure với 1 transaction để thêm 1 Order mới, với các OrderDetails, và cập nhật tồn kho (Stock) của các mặt hàng, gồm các bước:
- Kiểm tra tồn kho (Stock) của mặt hàng có ProductId = @ProductId, nếu Stock < @Quantity thì rollback transaction, và trả về lỗi 'Số lượng tồn kho không đủ'
- Tạo 1 Order mới, với Status = 'WAITING', CreatedDate = GETDATE(), EmployeeId = @EmployeeId, CustomerId = @CustomerId
- Tạo 1 OrderDetail mới, với OrderId = OrderId vừa tạo, ProductId = @ProductId, Quantity = @Quantity, Price = Product.Price, Discount = Product.Discount
- Cập nhật t ồn kho (Stock) của mặt hàng có ProductId = @ProductId, trừ đi @Quantity.