128 lines
4.9 KiB
SQL
128 lines
4.9 KiB
SQL
-- Lunch MiniApp MVP MySQL Schema
|
|
-- Assumption: MySQL 8.0+
|
|
-- Charset/Collation: utf8mb4
|
|
|
|
set names utf8mb4;
|
|
|
|
-- 1) users
|
|
create table if not exists app_user (
|
|
id char(36) not null,
|
|
provider varchar(32) not null default 'toss',
|
|
provider_user_id varchar(128) not null,
|
|
nick_name varchar(50) not null,
|
|
created_at timestamp not null default current_timestamp,
|
|
updated_at timestamp not null default current_timestamp on update current_timestamp,
|
|
primary key (id),
|
|
unique key uk_app_user_provider (provider, provider_user_id)
|
|
) engine=InnoDB default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;
|
|
|
|
-- 2) restaurants
|
|
create table if not exists restaurant (
|
|
id char(36) not null,
|
|
external_place_id varchar(128) null,
|
|
name varchar(120) not null,
|
|
category varchar(20) not null,
|
|
address varchar(255) not null,
|
|
phone varchar(30) null,
|
|
opening_hours text null,
|
|
lat double not null,
|
|
lng double not null,
|
|
is_active tinyint(1) not null default 1,
|
|
created_at timestamp not null default current_timestamp,
|
|
updated_at timestamp not null default current_timestamp on update current_timestamp,
|
|
primary key (id),
|
|
unique key uk_restaurant_external_place_id (external_place_id),
|
|
key idx_restaurant_lat_lng (lat, lng),
|
|
key idx_restaurant_category (category),
|
|
constraint chk_restaurant_category check (category in ('KOREAN','CHINESE','JAPANESE','WESTERN','OTHER'))
|
|
) engine=InnoDB default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;
|
|
|
|
-- 3) reviews (1 user : 1 restaurant)
|
|
create table if not exists restaurant_review (
|
|
id char(36) not null,
|
|
restaurant_id char(36) not null,
|
|
user_id char(36) not null,
|
|
rating tinyint not null,
|
|
content varchar(500) not null,
|
|
deleted_at timestamp null,
|
|
created_at timestamp not null default current_timestamp,
|
|
updated_at timestamp not null default current_timestamp on update current_timestamp,
|
|
primary key (id),
|
|
unique key uk_review_restaurant_user (restaurant_id, user_id),
|
|
key idx_review_restaurant_created_at (restaurant_id, created_at),
|
|
key idx_review_user_created_at (user_id, created_at),
|
|
constraint fk_review_restaurant foreign key (restaurant_id) references restaurant(id) on delete cascade,
|
|
constraint fk_review_user foreign key (user_id) references app_user(id) on delete cascade,
|
|
constraint chk_review_rating check (rating between 1 and 5)
|
|
) engine=InnoDB default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;
|
|
|
|
-- 4) likes (1 user : 1 restaurant)
|
|
create table if not exists restaurant_like (
|
|
restaurant_id char(36) not null,
|
|
user_id char(36) not null,
|
|
created_at timestamp not null default current_timestamp,
|
|
primary key (restaurant_id, user_id),
|
|
key idx_like_restaurant (restaurant_id),
|
|
key idx_like_user (user_id),
|
|
constraint fk_like_restaurant foreign key (restaurant_id) references restaurant(id) on delete cascade,
|
|
constraint fk_like_user foreign key (user_id) references app_user(id) on delete cascade
|
|
) engine=InnoDB default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;
|
|
|
|
-- 5) denormalized stats
|
|
create table if not exists restaurant_stat (
|
|
restaurant_id char(36) not null,
|
|
review_count int not null default 0,
|
|
like_count int not null default 0,
|
|
rating_sum int not null default 0,
|
|
average_rating decimal(3,2) not null default 0.00,
|
|
updated_at timestamp not null default current_timestamp on update current_timestamp,
|
|
primary key (restaurant_id),
|
|
constraint fk_stat_restaurant foreign key (restaurant_id) references restaurant(id) on delete cascade
|
|
) engine=InnoDB default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;
|
|
|
|
-- optional seed behavior:
|
|
-- insert into restaurant_stat (restaurant_id)
|
|
-- select r.id from restaurant r
|
|
-- on duplicate key update restaurant_id = values(restaurant_id);
|
|
|
|
-- 6) stat refresh procedure (call from app service after write)
|
|
drop procedure if exists refresh_restaurant_stat;
|
|
delimiter $$
|
|
create procedure refresh_restaurant_stat(in p_restaurant_id char(36))
|
|
begin
|
|
declare v_review_count int default 0;
|
|
declare v_like_count int default 0;
|
|
declare v_rating_sum int default 0;
|
|
declare v_average decimal(3,2) default 0.00;
|
|
|
|
select count(*), ifnull(sum(r.rating), 0)
|
|
into v_review_count, v_rating_sum
|
|
from restaurant_review r
|
|
where r.restaurant_id = p_restaurant_id
|
|
and r.deleted_at is null;
|
|
|
|
select count(*)
|
|
into v_like_count
|
|
from restaurant_like l
|
|
where l.restaurant_id = p_restaurant_id;
|
|
|
|
if v_review_count = 0 then
|
|
set v_average = 0.00;
|
|
else
|
|
set v_average = round(v_rating_sum / v_review_count, 2);
|
|
end if;
|
|
|
|
insert into restaurant_stat (
|
|
restaurant_id, review_count, like_count, rating_sum, average_rating, updated_at
|
|
) values (
|
|
p_restaurant_id, v_review_count, v_like_count, v_rating_sum, v_average, current_timestamp
|
|
)
|
|
on duplicate key update
|
|
review_count = values(review_count),
|
|
like_count = values(like_count),
|
|
rating_sum = values(rating_sum),
|
|
average_rating = values(average_rating),
|
|
updated_at = current_timestamp;
|
|
end $$
|
|
delimiter ;
|