CSDL BTL

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 34

TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

THÔNG TIN VÀ TRUYỀN THÔNG

BÁO CÁO FINNAL PROJECT


MÔN HỌC: THỰC HÀNH CƠ SỞ DỮ LIỆU
MÃ LỚP: 130990

Sinh viên thực hiện:


Nhóm 8
Trần Nhật Huy 20204988 – VN03 – K65
Ngũ Duy Vinh 20205049 – VN03 – K65
Bùi Đức Dũng 20204954 – VN03 – K65

Giáo viên hướng dẫn:


Thầy: Nguyễn Hữu Đức

Hà Nội, 2022

Food and Drink Order Page 1 of 34


Mục lục
1. Giới thiệu 3

1.1. Đặt vấn đề 3

1.2. Hệ thống đề nghị 3

1.3. Công nghệ 3

2. Phân tích yêu cầu người dùng 4

2.1. Đối tượng hướng tới 4

2.2. Danh sách chức năng 4

3. Thiết kế hệ thống 5

3.1. Sơ đồ cơ sở dữ liệu 5

3.2. Sơ đồ thực thể liên kết 6

3.3. Cấu trúc cơ sở dữ liệu 7

3.4. Index / Trigger 13

3.5. Truy vấn 18

3.6. Sơ đồ trang web 30

4. Kết luận 31

5. Phân công công việc 32

Food and Drink Order Page 2 of 34


1. Giới thiệu
1.1. Đặt vấn đề

Ngày nay Internet đã trở thành dịch vụ phổ biến và thiết yếu và có ảnh hưởng xâu rộng đến
thói quen sinh hoạt của con người. Cùng với đó thì các hình thức mua bán hàng hóa cho
mọi người ngày càng đa dạng và phát triển hơn. Các ứng dụng web cũng ngày càng đa dạng
phổ biến. Trước nhu cầu đó cùng với yêu cầu của môn học, nhóm chúng em quyết định thiết
kế một trang web quản lý mua bán thức ăn và đồ uống.

1.2. Hệ thống đề nghị

Tên hệ thống: Food and Drink Order Project


Yêu cầu hệ thống: Xây dựng được 1 hệ thống mua bán đồ ăn online, có sự đơn giản, nhanh
gọn, tiện lợi đối với người sử dụng.

1.3. Công nghệ sử dụng

CSDL : POSTGRESQL
Backend: Framework Ruby on Rails (v6.1.4.1)

Frontend: Reactjs (v18.2.0)

Mô hình : Client – Server

Food and Drink Order Page 3 of 34


2. Phân tích yêu cầu người dùng
2.1. Đối tượng người dùng hướng tới

- Chủ các nhà hàng, quán ăn muốn tìm 1 nơi phân phối đồ ăn online
- Người dùng muốn tìm 1 nơi để đặt đồ ăn nhanh, thức uống 1 cách nhanh chóng, tiện
lợi.

2.2. Danh sách chức năng

⮚ Khách hàng chưa có tài khoản:

o Đăng ký cửa hàng / người dùng

o Xem tất cả sản phẩm

o Tìm kiếm

o Đăng nhập

⮚ Chủ nhà hàng, quán ăn:

o Thêm, xem, sửa, xóa sản phẩm

o Đăng nhập / đăng xuất

⮚ Admin:

o Xem, xóa sản phẩm, cửa hàng

o Xem, chấp nhận, hủy đơn hàng người dùng

⮚ Người dùng đã đăng ký tài khoản:

o Xem tất cả sản phẩm

o Tìm kiếm

o Đánh giá sản phẩm

o Đặt hàng

o Đăng xuất

Food and Drink Order Page 4 of 34


3. Thiết kế hệ thống
a. Sơ đồ cơ sở dữ liệu:

https://drive.google.com/file/d/1h3VOFhUrJo3Cv-
lwxpTmYpi_FTiz1b2D/view?usp=sharing

Food and Drink Order Page 5 of 34


b. Sơ đồ quan hệ thực thể liên kết:

https://drive.google.com/file/d/1h3VOFhUrJo3Cv-
lwxpTmYpi_FTiz1b2D/view?usp=sharing

Food and Drink Order Page 6 of 34


c. Cấu trúc cơ sở dữ liệu:
1. Bảng ‘users’: chứa dữ liệu người dùng

CREATE TABLE public.users (

id bigint NOT NULL PRIMARY KEY,

first_name character varying NOT NULL,

last_name character varying NOT NULL,

username character varying NOT NULL,

password_digest character varying,

address character varying,

admin boolean DEFAULT false,

email character varying,

phone_number character varying,

image character varying DEFAULT 'https://i.stack.imgur.com/l60Hf.png'::character


varying,

created_at timestamp(6) without time zone NOT NULL,

updated_at timestamp(6) without time zone NOT NULL);

Food and Drink Order Page 7 of 34


2. Bảng ‘store’: Thông tin chủ nhà hàng

CREATE TABLE public.stores (

id bigint NOT NULL PRIMARY KEY,

store_name character varying,

store_address character varying,

password_digest character varying,

email character varying,

image character varying,

created_at timestamp(6) without time zone NOT NULL,

updated_at timestamp(6) without time zone NOT NULL

);

Food and Drink Order Page 8 of 34


3. Bảng ‘products’: Thông tin sản phẩm trong từng cửa hàng

CREATE TABLE public.products (

id bigint NOT NULL PRIMARY KEY,

name character varying,

description character varying,

image character varying,

price integer,

rating double precision DEFAULT 0.0,

store_id bigint NOT NULL,

category_id bigint NOT NULL,

created_at timestamp(6) without time zone NOT NULL,

updated_at timestamp(6) without time zone NOT NULL

);

ALTER TABLE ONLY public.products

ADD CONSTRAINT fk_rails_5cf8ff66a6 FOREIGN KEY (store_id) REFERENCES


public.stores(id) ON DELETE CASCADE;

ADD CONSTRAINT fk_rails_fb915499a4 FOREIGN KEY (category_id)


REFERENCES public.categories(id);

Food and Drink Order Page 9 of 34


4. Bảng ‘category’: Thông tin loại sản phẩm

CREATE TABLE public.categories (

id bigint NOT NULL PRIMARY KEY,

name character varying);

5. Bảng ‘rating’: Thông tin đánh giá sản phẩm

CREATE TABLE public.ratings (

id bigint NOT NULL PRIMARY KEY,

user_id bigint NOT NULL,

product_id bigint NOT NULL,

vote integer,

comment text,

created_at timestamp(6) without time zone NOT NULL,

updated_at timestamp(6) without time zone NOT NULL);

ALTER TABLE ONLY public.ratings

ADD CONSTRAINT fk_rails_a7dfeb9f5f FOREIGN KEY (user_id) REFERENCES


public.users(id) ON DELETE CASCADE;

ADD CONSTRAINT fk_rails_f846e598a7 FOREIGN KEY (product_id) REFERENCES


public.products(id) ON DELETE CASCADE;

Food and Drink Order Page 10 of 34


6. Bảng ‘orders’: Thông tin đơn đặt hàng

CREATE TABLE public.orders (

id bigint NOT NULL PRIMARY KEY,

user_id bigint NOT NULL,

receiver_name character varying,

receiver_phone character varying,

status integer DEFAULT 0,

total double precision DEFAULT 0.0,

created_at timestamp(6) without time zone NOT NULL,

updated_at timestamp(6) without time zone NOT NULL

);

ALTER TABLE ONLY public.orders

ADD CONSTRAINT fk_rails_f868b47f6a FOREIGN KEY (user_id) REFERENCES


public.users(id) ON DELETE CASCADE;

Food and Drink Order Page 11 of 34


7. Bảng ‘order-product’: Thông tin đơn đặt hàng gắn với sản phẩm

CREATE TABLE public.order_products (

id bigint NOT NULL PRIMARY KEY,

product_id bigint NOT NULL,

order_id bigint NOT NULL,

quantity integer,

created_at timestamp(6) without time zone NOT NULL,

updated_at timestamp(6) without time zone NOT NULL

);

ALTER TABLE ONLY public.order_products

ADD CONSTRAINT fk_rails_96c0709f78 FOREIGN KEY (product_id) REFERENCES


public.products(id) ON DELETE CASCADE;

ADD CONSTRAINT fk_rails_f40b8ccee4 FOREIGN KEY (order_id) REFERENCES


public.orders(id) ON DELETE CASCADE;

Food and Drink Order Page 12 of 34


d. Index, Trigger

1. Index:

CREATE UNIQUE INDEX index_order_products_on_id_and_order_id ON


public.order_products USING btree (id, order_id);

CREATE INDEX index_order_products_on_order_id ON public.order_products USING


btree (order_id);

CREATE INDEX index_order_products_on_product_id ON public.order_products USING


btree (product_id);

CREATE INDEX index_orders_on_user_id ON public.orders USING btree (user_id);

CREATE INDEX index_products_on_category_id ON public.products USING btree


(category_id);

CREATE INDEX index_products_on_store_id ON public.products USING btree (store_id);

CREATE INDEX index_ratings_on_product_id ON public.ratings USING btree


(product_id);

CREATE INDEX index_ratings_on_user_id ON public.ratings USING btree (user_id);

CREATE INDEX products_name_idx ON public.products USING btree (name);

CREATE INDEX stores_email_idx ON public.stores USING btree (email);

CREATE INDEX users_email_idx ON public.users USING btree (email);

Food and Drink Order Page 13 of 34


2. Function:

CREATE FUNCTION public.ratings_after_insert_update_row_tr() RETURNS trigger

LANGUAGE plpgsql

AS $$

BEGIN

UPDATE products

SET rating = (SELECT AVG(vote) FROM ratings WHERE product_id =


NEW.product_id)

WHERE id = NEW.product_id;

RETURN NULL;

END;

$$;

-----------------------------------------------------------------------------------------------

CREATE FUNCTION public.ratings_after_delete_row_tr() RETURNS trigger

LANGUAGE plpgsql

AS $$

BEGIN

UPDATE products

SET rating = (SELECT AVG(vote) FROM ratings WHERE product_id =


OLD.product_id)

WHERE id = OLD.product_id;

RETURN NULL;

END;

$$;

Food and Drink Order Page 14 of 34


CREATE FUNCTION public.order_products_after_delete_row_tr() RETURNS trigger

LANGUAGE plpgsql

AS $$

BEGIN

WITH total_cost AS (

SELECT SUM(products.price * order_products.quantity) AS "cost" FROM


order_products

JOIN products ON order_products.product_id = products.id

WHERE order_products.order_id = OLD.order_id

UPDATE orders

SET total = (SELECT * FROM total_cost)

WHERE id = OLD.order_id;

RETURN NULL;

END;

$$;

Food and Drink Order Page 15 of 34


CREATE FUNCTION public.order_products_after_insert_update_row_tr() RETURNS
trigger

LANGUAGE plpgsql

AS $$

BEGIN

WITH total_cost AS (

SELECT SUM(products.price * order_products.quantity) AS "cost" FROM


order_products

JOIN products ON order_products.product_id = products.id

WHERE order_products.order_id = NEW.order_id

UPDATE orders

SET total = (SELECT * FROM total_cost)

WHERE id = NEW.order_id;

RETURN NULL;

END;

$$;

Food and Drink Order Page 16 of 34


3. Trigger:

- Cập nhật tổng giá trị đơn hàng khi xóa sản phẩm trong đơn hàng:

CREATE TRIGGER order_products_after_delete_row_tr AFTER DELETE ON


public.order_products FOR EACH ROW EXECUTE FUNCTION
public.order_products_after_delete_row_tr();

- Cập nhật tổng giá trị đơn hàng khi thêm / cập nhật sản phẩm trong đơn
hàng:

CREATE TRIGGER order_products_after_insert_update_row_tr AFTER INSERT OR


UPDATE ON public.order_products FOR EACH ROW EXECUTE FUNCTION
public.order_products_after_insert_update_row_tr();

- Cập nhật đánh giá sản phẩm khi xóa 1 nhận xét:

CREATE TRIGGER ratings_after_delete_row_tr AFTER DELETE ON public.ratings FOR


EACH ROW EXECUTE FUNCTION public.ratings_after_delete_row_tr();

- Cập nhật đánh giá sản phẩm khi thêm / sửa 1 nhận xét:

CREATE TRIGGER ratings_after_insert_update_row_tr AFTER INSERT OR UPDATE


ON public.ratings FOR EACH ROW EXECUTE FUNCTION
public.ratings_after_insert_update_row_tr();

Food and Drink Order Page 17 of 34


e. Các truy vấn

-- 1) Tìm kiếm những người dùng đã đặt sản phẩm nào đó:

SELECT users.user_id, users.username FROM users


JOIN orders ON orders.user_id = users.id
JOIN order_products ON orders.id = order_products.order_id
JOIN products ON products.id = order_products.product_id
WHERE product_name = 'Vegetable Soup';

C1: Giới hạn những dữ liệu ở những bảng join (thay vì lấy tất cả thông tin thì ta chỉ cần
lấy ra những thông tin cần thiết):
SELECT users.id, users.first_name, users.last_name FROM users
NATURAL JOIN (SELECT orders.id AS order_id, orders.user_id AS "id" FROM
orders) AS "orders"
NATURAL JOIN (SELECT order_products.order_id, order_products.product_id
FROM order_products) AS "order_products"
NATURAL JOIN (SELECT products.id AS "product_id", products.name AS
"product_name" FROM products) AS "products"
WHERE product_name = 'Vegetable Soup';

➔Kết luận thời gian đã giảm (từ 32s → 21.5s) nhưng thời gian truy vấn vẫn còn rất lâu.

Food and Drink Order Page 18 of 34


C2: Thêm index vào trường products.name
SELECT
users.id,
users.first_name,
users.last_name
FROM
users
INNER JOIN orders AS "orders" ON orders.user_id = users.id
INNER JOIN order_products AS "order_products" ON order_products.order_id =
orders.id
INNER JOIN products AS "products" ON products.id = order_products.id
WHERE
products.name = 'Vegetable Soup';

➔ Truy vấn đã nhanh hơn rất nhiều. (Nhanh nhất là 2s và chậm nhất là 9s)

-- 2) Tìm kiếm người dùng theo email:


SELECT * FROM users
WHERE email = 'hello@example.com';

Food and Drink Order Page 19 of 34


-- 3) Tìm kiếm những cửa hàng có bán sản phẩm a:
SELECT DISTINCT stores.id, stores.store_name FROM stores
JOIN products ON stores.id = products.store_id
WHERE products.name = 'a';

-- 4) Tìm kiếm những sản phẩm được bán ở cửa hàng a:


SELECT products.id, products.name FROM products
JOIN stores ON products.store_id = stores.id
WHERE stores.store_name = 'a';

-- 5) Tìm kiếm những sản phẩm theo loại:


SELECT * FROM products
LEFT JOIN categories ON categories.id = products.category_id
WHERE categories.name = 'Food';

Food and Drink Order Page 20 of 34


-- 6) Tìm kiếm những sản phẩm chưa được bán lần nào:
SELECT * FROM products
WHERE products.id NOT IN (SELECT DISTINCT order_products.product_id FROM
order_products);

-- 7) Tìm kiếm những người dùng chưa mua hàng lần nào
SELECT users.id, users.first_name, users.last_name FROM users
WHERE users.id NOT IN (SELECT DISTINCT orders.user_id FROM orders);

Food and Drink Order Page 21 of 34


-- 8) Tìm kiếm những sản phẩm có đánh giá cao nhất:
SELECT products.id, products.name, products.rating FROM products
WHERE products.rating = (SELECT MAX(products_temp.rating) FROM products AS
products_temp);

-- 9) Trả về tất cả lượt đánh giá của 1 users:


SELECT users.first_name, users.last_name, ratings.comment FROM ratings
JOIN users ON ratings.user_id = users.id
WHERE users.first_name = 'Arianne';

Food and Drink Order Page 22 of 34


-- 10) Tất cả những đánh giá của một sản phẩm:
SELECT products.name, ratings.comment FROM products
JOIN ratings ON products.id = ratings.product_id
WHERE products.name = 'Vegetable Soup';

-- 11) Trả về những sản phẩm đã mua trong đơn hàng:


SELECT * FROM order_products
JOIN orders ON orders.id = order_products.order_id
WHERE orders.id = 2;

-- 12) Trả về tất cả những người dùng:


SELECT * FROM users;

-- 13) Trả về tất cả những sản phẩm có giá trong khoảng (10000, 20000):
SELECT * FROM products
WHERE products.price BETWEEN 10000 AND 20000;

Food and Drink Order Page 23 of 34


-- 14) Trả về những cửa hàng có trên 5 sản phẩm:
SELECT stores.id, stores.store_name FROM stores
JOIN products ON products.store_id = stores.id
GROUP BY stores.id
HAVING COUNT(*) > 5;

-- 15) Số đơn đặt hàng đc đặt của một sản phẩm trong hôm nay:
SELECT COUNT(order_products.id) FROM order_products
NATURAL JOIN (SELECT products.id AS product_id, products.name FROM products)
AS products
WHERE products.name = 'Vegetable Soup' AND DATE(order_products.created_at) =
CURRENT_DATE;

Food and Drink Order Page 24 of 34


-- 16) Số người dùng đăng ký thành công trong ngày hôm nay:
SELECT COUNT(users.id) FROM users
WHERE DATE(users.created_at) = CURRENT_DATE;

-- 17) Số lượng mặt hàng được mua của một cửa hàng trong một ngày:
SELECT COUNT(*) FROM products
JOIN stores ON stores.id = products.store_id
JOIN order_products ON order_products.product_id = products.id
WHERE stores.store_name = 'Golden Sushi' AND DATE(order_products.created_at) =
CURRENT_DATE;

-- 18) Đưa ra những rating của sản phẩm cao nhất và thấp nhất:
SELECT MAX(rating) "highest_rating", MIN(rating) "lowest_rating" FROM products;

Food and Drink Order Page 25 of 34


-- 19) Tìm kiếm những người dùng đã mua hàng trong hôm nay:
SELECT DISTINCT users.id, users.username FROM users
JOIN orders ON orders.user_id = users.id;

-- 20) Đưa ra tên những cửa hàng không bán sản phẩm nào:
SELECT stores.id, stores.store_name FROM stores
LEFT JOIN products ON products.store_id = stores.id
GROUP BY stores.id
HAVING COUNT(*) = 0;

Food and Drink Order Page 26 of 34


-- 21) Đưa ra những đơn hàng chưa được admin chấp nhận:
SELECT * FROM orders
WHERE status = 0;

-- 22) Tìm kiếm những sản phẩm mà người dùng chưa đặt lần nào:
SELECT products.id, products.name FROM products
WHERE products.id NOT IN (SELECT DISTINCT order_products.product_id FROM
order_products
JOIN orders ON order_products.order_id = orders.id
JOIN users ON users.id = orders.user_id
WHERE users.username = 'Bradley Abbott');

Food and Drink Order Page 27 of 34


-- 23) Tìm kiếm những sản phẩm có rating trong khoảng (2, 4):
SELECT products.id, products.name FROM products
WHERE products.rating BETWEEN 2 AND 4;

-- 24) Tìm kiếm những cửa hàng có bán sản phẩm loại a:
SELECT DISTINCT stores.id, stores.store_name FROM stores
JOIN products ON products.store_id = stores.id
WHERE products.category_id = (SELECT categories.id FROM categories WHERE
categories.name = 'Food');

Food and Drink Order Page 28 of 34


-- 25) Tìm kiếm những đơn hàng mà một người đã mua:
WITH user_order_id AS (
SELECT orders.id FROM orders
JOIN users ON orders.user_id = users.id
WHERE users.username = 'Bradley Abbott'
)
SELECT * FROM order_products
WHERE order_products.order_id IN (SELECT * FROM user_order_id);

-- 26) Tìm kiếm những đơn hàng mà người dùng đã mua trong hôm nay:
WITH user_order_id AS (
SELECT orders.id FROM orders
JOIN users ON orders.user_id = users.id
WHERE users.username = 'Bradley Abbott'
)
SELECT * FROM order_products
WHERE order_products.order_id IN (SELECT * FROM user_order_id) AND
DATE(created_at) = CURRENT_DATE;

Food and Drink Order Page 29 of 34


-- 27) Tìm kiếm những đơn hàng có số lượng trên 10 sản phẩm:
SELECT * FROM order_products
WHERE order_products.quantity > 10;

-- 28) Tìm kiếm những cửa hàng theo địa chỉ:


SELECT * FROM stores
WHERE stores.store_address = 'Hanoi';

Food and Drink Order Page 30 of 34


-- 29) Thống kê những người dùng đã mua hàng tại cửa hàng kèm địa chỉ:
SELECT DISTINCT users.id, users.username, users.address FROM users
NATURAL JOIN (SELECT orders.id AS order_id, orders.user_id AS "id" FROM orders)
AS "orders"
NATURAL JOIN (SELECT order_products.order_id, order_products.product_id FROM
order_products) AS "order_products"
NATURAL JOIN (SELECT products.id AS "product_id", products.store_id FROM
products) AS "products"
NATURAL JOIN (SELECT stores.id AS "store_id", stores.store_name FROM stores) AS
"stores"
WHERE stores.store_name = 'Golden Sushi' AND users.address = 'Hanoi';

-- 30) Số lượng sản phẩm đã mua theo từng sản phẩm của người dùng trong một tháng:
SELECT products.product_id, products.product_name, SUM(order_products.quantity) AS
"Tong so luong" FROM users
NATURAL JOIN (SELECT orders.id AS order_id, orders.user_id AS "id" FROM orders)
AS "orders"
NATURAL JOIN (SELECT order_products.order_id, order_products.product_id,
order_products.quantity, order_products.created_at AS "ngay_mua" FROM order_products)
AS "order_products"
NATURAL JOIN (SELECT products.id AS "product_id", products.name AS
"product_name" FROM products) AS "products"
WHERE users.username = 'Bradley Abbott' AND EXTRACT(MONTH FROM
order_products.ngay_mua) = 7
GROUP BY (products.product_id, products.product_name);

Food and Drink Order Page 31 of 34


f. Sơ đồ trang web

Food and Drink Order Page 32 of 34


4. Kết luận:
4.1 Điểm mạnh:
- Các thành viên tích cực tham gia xây dựng phát triển ứng dụng.
- Xây dựng được hệ thống hoàn chỉnh đầy đủ các chức năng ưu tiên đề ra.
- Chủ cửa hàng dễ dàng thuận tiện, quản lý những sản phẩm của mình
- Giao diện người dùng dễ dùng, trực quan.

4.2 Điểm chưa tốt:


- Còn thiếu 1 số chức năng nâng cao như:
+ Lọc sản phẩm theo giá tiền
+ Quên mật khẩu
+ Theo dõi tình trạng đơn hàng theo thời gian thực
- Việc đặt hàng chỉ dừng lại ở giai đoạn xác nhận đơn hàng, chưa có chức
năng thanh toán.
- Hạn chế trong việc kiểm tra sản phẩm do sử dụng dữ liệu sinh tự động
- Loại sản phẩm còn sơ sài
- Xung đột trong việc lập trình backend do các thành viên sử các ngôn
ngữ lập trình khác nhau.

Food and Drink Order Page 33 of 34


5. Phân công công việc:

Họ và tên MSSV Nhiệm vụ

Trần Nhật Huy (Lead) 20204988 Thiết kế cơ sở dữ liệu, tạo api, tạo
function/trigger/index, viết truy vấn

Ngũ Duy Vinh (SubLead) 20205049 Thiết kế cơ sở dữ liệu, thiết kế giao


diện người dùng, viết truy vấn

Bùi Đức Dũng (Mem) 20204954 Phân tích bài toán, thiết kế cơ sở dữ
liệu, viết báo cáo, viết truy vấn

Food and Drink Order Page 34 of 34

You might also like