Mysql 数据库模式,表中的多个或布尔值

Mysql 数据库模式,表中的多个或布尔值,mysql,database,database-schema,Mysql,Database,Database Schema,如果我的数据库中有很多餐厅,每个餐厅都可以有午餐菜单、晚餐菜单或早午餐菜单,那么在餐厅表中使用布尔值是否有意义,如下所示: 餐厅id |餐厅名称|地址|等午餐菜单|晚餐菜单|早午餐菜单 或者我应该创建一个菜单表,然后创建一个RestaurantMenu表(多个关系) 菜单id |菜单名称 1 |午餐菜单 2 |晚餐菜单 3 |早午餐菜单我的建议是使用简单的位掩码类型的字段: 例如: 1 = breakfast 2 = brunch 4 = lunch 8 = dinner const int

如果我的数据库中有很多餐厅,每个餐厅都可以有午餐菜单、晚餐菜单或早午餐菜单,那么在餐厅表中使用布尔值是否有意义,如下所示:

餐厅id |餐厅名称|地址|等午餐菜单|晚餐菜单|早午餐菜单

或者我应该创建一个菜单表,然后创建一个RestaurantMenu表(多个关系)

菜单id |菜单名称

1 |午餐菜单

2 |晚餐菜单


3 |早午餐菜单

我的建议是使用简单的位掩码类型的字段:

例如:

1 = breakfast
2 = brunch
4 = lunch
8 = dinner
const int BREAKFAST = 1;
const int BRUNCH = 2;
const int LUNCH = 4;
const int DINNER = 8;

int RestaurantMenuType = 5;

bool OffsersBreakfastMenu = (RestaurantMenuType & BREAKFAST) == BREAKFAST;
bool OffsersBrunchMenu = (RestaurantMenuType & BRUNCH) == BRUNCH;
bool OffsersLunchMenu = (RestaurantMenuType & LUNCH) == LUNCH;
bool OffersDinnerMenu = (RestaurantMenuType & DINNER) == DINNER;

Console.WriteLine("Offers breakfast? {0}", OffsersBreakfastMenu ? "Yes" : "No");
Console.WriteLine("Offers brunch? {0}", OffsersBrunchMenu ? "Yes" : "No");
Console.WriteLine("Offers lunch? {0}", OffsersLunchMenu ? "Yes" : "No");
Console.WriteLine("Offers dinner? {0}", OffersDinnerMenu ? "Yes" : "No");
如果有必要,您可以添加更多

如果一家餐厅既有早餐也有午餐,但既没有早午餐也没有晚餐,那么这是1+4,因此列得到5

如果一家餐厅具备以上所有条件,那就是1+2+4+8,也就是15

然而,对于未来的数据库维护人员来说,它可能不是最具可读性的。然而,让一列指示多个选项是一种简单的方法

编辑:

这只是简单的二进制操作。它的工作原理如下:

Dinner   Lunch   Brunch   Breakfast
-------- ------- -------- ---------
0        0       0        1             1 (Breakfast only)
1        1       0        0             12 (Dinner + Lunch)
1        1       1        1             15 (All four)
restaurants
---------------
id    name
1     Moe's
2     Steak & Shrimp House
3     McDonald's

restaurant_menus
----------------
restaurant_id    menu_type
1                1
1                3
2                4
3                1
3                3
3                4

menu_types
---------------
id    type
1     Breakfast
2     Brunch
3     Lunch
4     Dinner
SELECT r.name, mt.type
FROM restaurants r
    JOIN restaurant_menus rm
        ON (r.id = rm.restaurant_id)
    JOIN menu_types mt
        ON (rm.menu_type = mt.id)
ORDER BY r.name ASC;
这种字段的优点是,假设int字段存储了足够的位,您可以在不更改数据库的情况下添加其他菜单类型

在您的程序中,您可以通过某些位运算符确定可用的菜单类型。例如,在C#中:

1 = breakfast
2 = brunch
4 = lunch
8 = dinner
const int BREAKFAST = 1;
const int BRUNCH = 2;
const int LUNCH = 4;
const int DINNER = 8;

int RestaurantMenuType = 5;

bool OffsersBreakfastMenu = (RestaurantMenuType & BREAKFAST) == BREAKFAST;
bool OffsersBrunchMenu = (RestaurantMenuType & BRUNCH) == BRUNCH;
bool OffsersLunchMenu = (RestaurantMenuType & LUNCH) == LUNCH;
bool OffersDinnerMenu = (RestaurantMenuType & DINNER) == DINNER;

Console.WriteLine("Offers breakfast? {0}", OffsersBreakfastMenu ? "Yes" : "No");
Console.WriteLine("Offers brunch? {0}", OffsersBrunchMenu ? "Yes" : "No");
Console.WriteLine("Offers lunch? {0}", OffsersLunchMenu ? "Yes" : "No");
Console.WriteLine("Offers dinner? {0}", OffersDinnerMenu ? "Yes" : "No");

另一个建议是使用链接器表。这将更易于维护和记录。当您具有多对多关系时,将使用链接器表。(一家餐厅可以有多种菜单类型,而一种特定类型的菜单可供许多餐厅使用。)

这使您可以在以后将其他菜单类型作为行添加到“菜单类型”表中,而无需更改任何表的结构

但是,这确实会使查询变得更加复杂,因为您必须执行一些连接

首先,您将有三个类似这样的表:

Dinner   Lunch   Brunch   Breakfast
-------- ------- -------- ---------
0        0       0        1             1 (Breakfast only)
1        1       0        0             12 (Dinner + Lunch)
1        1       1        1             15 (All four)
restaurants
---------------
id    name
1     Moe's
2     Steak & Shrimp House
3     McDonald's

restaurant_menus
----------------
restaurant_id    menu_type
1                1
1                3
2                4
3                1
3                3
3                4

menu_types
---------------
id    type
1     Breakfast
2     Brunch
3     Lunch
4     Dinner
SELECT r.name, mt.type
FROM restaurants r
    JOIN restaurant_menus rm
        ON (r.id = rm.restaurant_id)
    JOIN menu_types mt
        ON (rm.menu_type = mt.id)
ORDER BY r.name ASC;
因此,要查看每家餐厅提供什么样的菜单,您的查询如下:

Dinner   Lunch   Brunch   Breakfast
-------- ------- -------- ---------
0        0       0        1             1 (Breakfast only)
1        1       0        0             12 (Dinner + Lunch)
1        1       1        1             15 (All four)
restaurants
---------------
id    name
1     Moe's
2     Steak & Shrimp House
3     McDonald's

restaurant_menus
----------------
restaurant_id    menu_type
1                1
1                3
2                4
3                1
3                3
3                4

menu_types
---------------
id    type
1     Breakfast
2     Brunch
3     Lunch
4     Dinner
SELECT r.name, mt.type
FROM restaurants r
    JOIN restaurant_menus rm
        ON (r.id = rm.restaurant_id)
    JOIN menu_types mt
        ON (rm.menu_type = mt.id)
ORDER BY r.name ASC;
这将产生:

name                  type       
--------------------  -----------
McDonald's            Lunch      
McDonald's            Breakfast  
McDonald's            Dinner     
Moe's                 Breakfast  
Moe's                 Lunch      
Steak & Shrimp House  Dinner     

如果只有3个菜单列具有
bool
类型,则无需创建另一个表o,那么一家餐厅可以有多个菜单,还是只有这3个菜单中的一个?老实说,这个问题的答案取决于您是否认为需要将其他菜单类型添加到数据库中。如果您确定已经涵盖了所有类型,那么使用和查询
bool
列将非常简单。但是如果你不得不意外地添加一个,那可能会让人头疼。我提供了两个答案,展示了我用于可扩展性的两种方法。但是如果你有
4
,你会如何区分
3+1
?我想你的意思是
2^X
,对吧?但1+3=4和4也是晚餐。所以你需要0-没有菜单,1-早餐,2-早午餐,4-午餐,8-晚餐(2^n)我从一个伪造的二进制应用程序开始,然后编辑了答案。对此我深表歉意,因为我没有正确地进行精神上的转换。值应该是1、2、4、8等等,而不是1、2、3、4等等。这非常有用,但对于我的需要来说是不必要的。我的db在这一点上非常简单,因此您上面给出的解决方案似乎更实用。不过这很有趣。嘿,谢谢你的回答。现在我正在为一个iphone应用程序实现这个功能,我正在使用HTTP GET。下面是我正在使用的SQL查询,但它不包含联接。这是否足够有效?“从menu\u id所在的菜单中选择menu\u name(从餐厅中选择menu\u id\u menu WHERE Restaurants\u id='$restaurantID')”,我想说这是一个关于SQL查询效率的新问题。但总的来说,根据我的经验,子查询的效率不是很高;这取决于索引的实现和其他因素。