如何设计我的数据库以适应这些数据

时间:2014-09-12 15:50:02

标签: mysql database database-design

我正在为工资单应用程序开发一个数据库,我需要的一个功能是一个表,用于存储每个商店每周工作的员工列表。

每位员工都有一个ID,所以我的表格如下:

        |   Mon   |   Tue   |   Wed   |   Thu   |   Fri   |   Sat   |   Sun
Store 1 | 3,4,5   | 3,4,5   | 3,4,5   | 4,5,7   | 4,5,7   | 4,5,6,7 | 4,5,6,7
Store 2 | 1,8,9   | 1,8,9   | 1,8,9   | 1,8,9   | 1,8,9   | 1,8,9   | 1,8,9
Store 3 | 10,12   | 10,12   | 10,12   | 10,12   | 10,12   | 10,12   | 10,12
Store 4 | 15      | 15      | 15      | 16      | 16      | 16      | 16
Store 5 | 6,11,13 | 6,11,13 | 6,11,13 | 14,18,19| 14,18,19| 14,18,19| 14,18,19

我的问题是,如何在我的数据库中表示?我提出了以下想法:

创意1 :几乎复制了上面的设计,创建了一个包含以下列的表:[Store_id |周一|星期二... |周六| Sun]然后将每天的员工ID列表存储为字符串,ID以逗号分隔。我知道以逗号分隔的列表不是很好的数据库设计,但有时它们看起来很诱人,就像在这种情况下一样。

   Store_id |   Mon   |   Tue   |   Wed   |   Thu   |   Fri   |   Sat   
   ---------+---------+---------+---------+---------+---------+---------
        1   | '3,4,5' | '3,4,5' | '3,4,5' | '4,5,7' | '4,5,7' | '4,5,6,7' 
        2   | '1,8,9' | '1,8,9' | '1,8,9 '| '1,8,9' | '1,8,9' | '1,8,9'   

创意2 :创建一个包含以下列的表:[Store_id |一天|员工ID]。这样,在特定日期在特定商店工作的每个员工都将成为此表中的条目。我看到的问题是这个表会增长得非常快,而且在数据库级别可视化数据会更困难。

Store_id | Day | Employee_id
---------+-----+-------------
   1     | mon |     3
   1     | mon |     4
   1     | mon |     5
   1     | tue |     3
   1     | tue |     4

这些想法中的任何一个都可行吗?有没有更好的存储数据的方法?

3 个答案:

答案 0 :(得分:2)

第二种设计对于关系数据库是正确的。每行一个employee_id,即使每天每个商店产生多行。

如果您的示例准确,则行数不可能大于RDBMS可以处理的行数。每家商店每天不超过4名员工,5家商店,每年最多366天。所以每年不超过7320行,也许更少。

我经常看到MySQL中的数据库在给定的表中有数亿甚至数十亿行。因此,在遇到可伸缩性问题之前,您可以继续运行这些存储多年。

答案 1 :(得分:2)

如果我是你,我会存储员工数据并将数据存储在单独的表中......但仍保留主表的设计。所以做这样的事情

CREATE TABLE stores (
    id INT, -- make it the primary key auto increment.. etc
    store_name VARCHAR(255)
    -- any other data for your store here.
);

CREATE TABLE schedule (
    id INT, -- make it the primary key auto increment.. etc
    store_id INT, -- FK to the stores table id
    day VARCHAR(20),
    emp_id INT -- FK to the employees table id
);

CREATE TABLE employees
    id INT, -- make it the primary key auto increment.. etc
    employee_name VARCHAR(255)
    -- whatever other employee data you need to store.
);

我会为商店和员工提供一个表格,因为您可以为每个商店或员工提供特定数据

<强>奖金:

如果您希望查询显示商店名称以及员工姓名及其日程安排,那么您所要做的就是加入两个表

SELECT s.store_name, sh.day, e.employee_name
FROM schedule sh
JOIN stores s ON s.id = sh.store_id
JOIN employees e ON e.id = sh.emp_id

这个查询有一定的局限性,因为您无法按天订购,因此您可以随机获取数据..所以实际上您还需要一个包含当天特定数据的日期表,以便您可以在开始时订购数据或本周末。

如果你确实想要制作一个日期表,那将会是同样的事情

CREATE TABLE days(
    id INT,
    day_name VARCHAR(20),
    day_type VARCHAR(55)
    -- any more data you want here
)

其中日名称为Mon Tue ...而day_type将为Weekday或Weekend

然后你要为查询做的就是

SELECT s.store_name, sh.day, e.employee_name
FROM schedule sh
JOIN stores s ON s.id = sh.store_id
JOIN employees e ON e.id = sh.emp_id
JOIN days d ON d.id = sh.day_id
ORDER BY d.id

注意日计划表中的两个列将替换为链接到days表的day_id的一列。

希望有帮助!

答案 2 :(得分:2)

我赞成John Ruddell的回答,这基本上是你的选择#2,增加了表来保存关于商店和员工的数据。我不会重复他所说的话,但是我只想补充一些太长的评论意见:

永远不要将逗号分隔值放在数据库记录中。这使得数据更难以使用。

当然,无论是#1还是#2,都可以轻松查询周五在1号店工作的员工:

方法1:

select Friday_employees from schedule where store_id='store 1'

方法2:

select employee_id from schedule where store_id=1 and day='fri'

但是假设您想知道员工#7的工作日期。

使用方法2,很容易:

select day from schedule where employee_id=7

但你怎么用方法1做到这一点?你可以打破它的各个部分并检查每一块。充其量只是一种痛苦,而且我已经看到人们经常搞砸了,比如写作

where Friday_employees like '%7%'
嗯,除非有员工编号17或27怎么办?你也会得到它们。你可以说

where Friday_employees like '%,7,%'

但是如果7是列表中的第一个或最后一个,它就不起作用。

如果您希望用户能够选择一天,然后向他们提供当天工作的员工列表,该怎么办?

使用方法2,轻松:

select employee_id from schedule where day=@day

然后使用参数化查询填写值。

方法1 ......

select employee_id from schedule where case when @day='mon' then Monday_employees when @day='tue' then Tuesday_employees when @day='wed' then Wednesday_employees when @day='thu' then Thursday_employees when @day='fri' then Friday_employees when @day='sat' then Saturday_employees as day_employees

这是一头野兽,如果你做了很多事,迟早你会犯错误,留下一天或意外地输入“当天='星期四'然后星期五_雇员”或其他类似的东西。我见过这种情况经常发生。

即使您编写那些冗长复杂的查询,性能也会很糟糕。如果您有employee_id字段,则可以对其进行索引,因此员工访问速度很快。如果您有一个以逗号分隔的员工列表,那么查询“喜欢'%,7,%'的品种需要按顺序搜索数据库中的每条记录。