简体   繁体   English

数据库设计-我的数据应该有多精细?

[英]Database design - How granular should my data be?

Suppose I have an application that renders a seating chart to the user. 假设我有一个向用户呈现座位表的应用程序。

There are three seating sections. 一共有三个座位区。

Each section contains five rows. 每个部分包含五行。

Each row contains a variable number of seats. 每行包含可变数量的座位。

Each seat has its own attributes, among which is an association with the customer who has purchased the seat. 每个席位都有自己的属性,其中包括与购买席位的客户的关联。

Would it make sense for me to model the data into the following tables? 将数据建模到下表中对我来说有意义吗?

  • floor_plan 平面图
  • seating_section 就座区
  • seating_row 座位行
  • seat 座位
  • customer 顾客

Ultimately, this data will need to be aggregated so that it is meaningful and useful to my front end. 最终,将需要汇总这些数据,以使其对我的前端有意义并有用。 How does one go about assembling data from the database into something that is useful for and specific to a given view? 如何将数据库中的数据组合成对给定视图有用且特定于视图的东西?

Also, I have a gazillion more questions regarding similar database-design-related items. 此外,关于类似的数据库设计相关项目,我还有无数个问题。 Are there any good books that could give me a solid foundation in this stuff? 有什么好书可以为我提供扎实的基础吗?

From the relational point of view, data should be granular enough that 从关系的角度来看,数据应该足够细,以至于

  • the dbms can enforce sensible constraints on it, and dbms可以对其施加强制性的约束,并且
  • client code never has to parse it. 客户代码永远不必解析它。

Assuming there's only one venue (only one floorplan), the enterprise will typically identify a seat by its section, row, and number. 假设只有一个场所(只有一个平面图),则企业通常会通过其部分,行和编号来识别座位。 Principles are the same for multiple floorplans and multiple venues. 多个平面图和多个场所的原则是相同的。

Let's assume that section 1 has 3 rows, section 2 has 5 rows, and section 3 has 4 rows. 假设第1节有3行,第2节有5行,第3节有4行。 (Tested in PostgreSQL.) (在PostgreSQL中测试。)

create table sections (
  section_num integer primary key
    check (section_num between 1 and 3)
);

insert into sections values (1), (2), (3);

create table section_rows (
  section_num integer not null
    references sections (section_num),
  row_num integer not null
    check (row_num between 1 and 5),
  primary key (section_num, row_num)
);

insert into section_rows values
(1,1), (1,2), (1,3),
(2,1), (2,2), (2,3), (2,4), (2,5),
(3,1), (3,2), (3,3), (3,4);

create table seats (
  section_num integer not null,
  row_num integer not null,
  seat_num integer not null,
  primary key (section_num, row_num, seat_num),
  foreign key (section_num, row_num) 
    references section_rows (section_num, row_num)
);

insert into seats values
(1, 1, 1), (1, 1, 2), (1, 1, 3),
(1, 2, 1), (1, 2, 2), (1, 2, 3),
(1, 3, 1), (1, 3, 2), (1, 3, 3), (1, 3, 4),
(2, 1, 1), (2, 1, 2), (2, 1, 3),
(2, 2, 1), (2, 2, 2), (2, 2, 3),
(2, 3, 1), (2, 3, 2), (2, 3, 3), (2, 3, 4),
(2, 4, 1), (2, 4, 2), (2, 4, 3), (2, 4, 4),
(2, 5, 1), (2, 5, 2), (2, 5, 3), (2, 5, 4), (2, 5, 5),
(3, 1, 1), (3, 1, 2), (3, 1, 3),
(3, 2, 1), (3, 2, 2), (3, 2, 3),
(3, 3, 1), (3, 3, 2), (3, 3, 3), (3, 3, 4),
(3, 4, 1), (3, 4, 2), (3, 4, 3), (3, 4, 4);

This last table, "seats" identifies every seat in the venue. 最后一个表格“座位”标识了场地中的每个座位。 Once these three tables are populated, you never have to change them unless you tear out seats or install new ones. 一旦填充了这三个表,您就不必更改它们,除非您拆下座椅或安装新的座椅。

Now you can sell each one to a customer. 现在您可以将每一个出售给客户。

create table event_sales (
  -- Assumes an event identifier identifies the date and time as well
  -- as the event's name.
  event_id integer not null, -- references events (not shown)
  section_num integer not null,
  row_num integer not null,
  seat_num integer not null,
  customer_columns_go_here char(1) default 'x',
  primary key (event_id, section_num, row_num, seat_num),
  foreign key (section_num, row_num, seat_num) 
    references seats (section_num, row_num, seat_num)
);

insert into event_sales values
(1, 1, 1, 1, 'a'),
(1, 1, 1, 2, 'a'),
(1, 1, 1, 3, 'a'),
(1, 2, 2, 1, 'b'),
(2, 2, 1, 1, 'a'),
(2, 2, 1, 2, 'b'),
(2, 2, 1, 3, 'c'),
(2, 3, 2, 1, 'd');

All these tables are in at least 5NF. 所有这些表都至少为5NF。

What seats are available for event 1? 活动1有哪些座位? (Probably the most common query for a seating application.) (这可能是就座应用程序最常见的查询。)

select *
from seats
except
(select section_num, row_num, seat_num from event_sales where event_id = 1)
order by section_num, row_num, seat_num;

Database design is a bigger topic than most people think it is. 数据库设计是一个比大多数人想象的更大的话题。 You're not likely to get it right by skimming a couple of web sites. 通过浏览两个网站,您不太可能解决问题。 Avoid bad practices while you learn. 在学习时避免不良作法。 I think you're probably best served by Bill Karwin's book SQL Antipatterns: Avoiding the Pitfalls of Database Programming . 我认为,Bill Karwin的书SQL Antipatterns :避免数据库编程的陷阱可能最适合您。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM