Chris Asked: 2020-02-07 08:58:08 +0800 CST2020-02-07 08:58:08 +0800 CST 2020-02-07 08:58:08 +0800 CST 可以在关系数据库中添加表年份吗? 772 我如何向我的同事解释这是不必要的复杂性和冗余数据? 他想要一张年份表,因为许多表都有“年份”值,而且他还想要有名称和年份的关系表,这会增加不必要的内部连接和外来我坚持认为这是错误的,我只想确保这不是一个好习惯...... sql-server mysql 3 个回答 Voted Best Answer Rick James 2020-02-11T10:34:40+08:002020-02-11T10:34:40+08:00 vehicle_year应该是数据类型YEAR。 日期应该是 datatype DATE。即使您需要将日期拆分为其组成部分,这样做几乎总是比使用包含日期及其部分的维度表更好。 一般来说,不要“规范化”任何“连续”值——日期、整数、浮点数等。 正如 kevensky 指出的那样,对于需要在缺失年份(或其他任何内容)显示零的“报告”,有一个用例可以朝另一个方向发展。但这并没有以任何方式链接到主表。相反,它被用来像 SELECT y.year, COALESCE(SUM(m.stuff), 0), ... FROM Years AS y LEFT JOIN my_table AS m GROUP BY... 请注意如何LEFT JOIN包括 Years 表中的所有年份。(您可能希望使用WHERE子句来限制范围。) 而COALESCE是用来把NULL缺失的年份变成0。或N/A。或No data。管他呢。 虽然我在这里,但我建议规范化“模型”也是“过度规范化”。Vehicle表格中拼出的型号名称非常好。 什么时候应该正常化? 不是唯一的——人们的名字。 当值可能发生变化时——车主(但这需要一个多:多表) 有很多辅助数据——公司(有地址等) 节省空间——名字长,桌子大;不适用于 2-letter country_code 与 4-byte INT。 型号年份是自我识别的,从不改变,不大,没有辅助数据。 车辆品牌和型号大多与车型年份相似。同样适用于发动机尺寸、颜色、价格等。 让我提出一个假设性的问题:“雪佛兰生产他们的 Impala 模型是几年(model_years,即)?” 这可以通过“SELECT DISTINCT model_year FROM Vehicle WHERE make = ...;”来回答。这可以从表中的可用车辆中得到答案。 或者,您可能从列出答案的历史网站上获得它。现在你需要一张桌子,上面有PRIMARY KEY(make, model)关于旧车历史的各种信息。 这导致了一个更混乱的情况——分层信息。注:通用 > 雪佛兰 > Impala > LT。“位置”有类似的问题:美国 > 乔治亚 > 富尔顿县 > 亚特兰大 > 地址。通常,每个级别的规范化都是大材小用,应该避免。 因为许多表都有“年份”值 好吧,规范化的“教科书”论点在这里惨败。它说您应该规范化,以便将值放在一个位置以便于更改。但是,如果这year代表车辆的 model_year 在一张桌子上,但您孩子的生日在另一张桌子上,而您的毕业日期在另一张桌子上,那么您当然不想更改该值。 将规范化表想象成一个“实体”,例如一个人、一个地方、一个公司、一张图片、一个网络帖子等。你给实体一个唯一的标识符 ( PRIMARY KEY) 以便每个人都可以轻松地引用它。在表格中,您有一个可打印的名称、一个位置、一个“点赞”计数器等。 kevinskio 2020-02-07T09:08:43+08:002020-02-07T09:08:43+08:00 我使用了一个年份表来报告使用适当数量的过滤器可能在该年没有任何结果的情况。客户仍然想查看当年的金额,即使它是零。通过拥有一张年份表,您可以保证每个年份都有一个值。另一种方法是进行外部连接,我认为这会因需要更多扫描而影响性能。 您的用例可能会有所不同,但这并不总是一个坏主意 watery 2020-02-07T09:08:47+08:002020-02-07T09:08:47+08:00 作为一个快速的答案,我会说你正在使用一个数字来关联另一个数字——而且只有那个(那个年份表中没有额外的价值)。 然后,正如您已经说过的,查询多年将需要额外的努力(连接、子查询等)。
vehicle_year
应该是数据类型YEAR
。日期应该是 datatype
DATE
。即使您需要将日期拆分为其组成部分,这样做几乎总是比使用包含日期及其部分的维度表更好。一般来说,不要“规范化”任何“连续”值——日期、整数、浮点数等。
正如 kevensky 指出的那样,对于需要在缺失年份(或其他任何内容)显示零的“报告”,有一个用例可以朝另一个方向发展。但这并没有以任何方式链接到主表。相反,它被用来像
请注意如何
LEFT JOIN
包括 Years 表中的所有年份。(您可能希望使用WHERE
子句来限制范围。)而
COALESCE
是用来把NULL
缺失的年份变成0
。或N/A
。或No data
。管他呢。虽然我在这里,但我建议规范化“模型”也是“过度规范化”。
Vehicle
表格中拼出的型号名称非常好。什么时候应该正常化?
INT
。型号年份是自我识别的,从不改变,不大,没有辅助数据。
车辆品牌和型号大多与车型年份相似。同样适用于发动机尺寸、颜色、价格等。
让我提出一个假设性的问题:“雪佛兰生产他们的 Impala 模型是几年(model_years,即)?”
这可以通过“SELECT DISTINCT model_year FROM Vehicle WHERE make = ...;”来回答。这可以从表中的可用车辆中得到答案。
或者,您可能从列出答案的历史网站上获得它。现在你需要一张桌子,上面有
PRIMARY KEY(make, model)
关于旧车历史的各种信息。这导致了一个更混乱的情况——分层信息。注:通用 > 雪佛兰 > Impala > LT。“位置”有类似的问题:美国 > 乔治亚 > 富尔顿县 > 亚特兰大 > 地址。通常,每个级别的规范化都是大材小用,应该避免。
好吧,规范化的“教科书”论点在这里惨败。它说您应该规范化,以便将值放在一个位置以便于更改。但是,如果这
year
代表车辆的 model_year 在一张桌子上,但您孩子的生日在另一张桌子上,而您的毕业日期在另一张桌子上,那么您当然不想更改该值。将规范化表想象成一个“实体”,例如一个人、一个地方、一个公司、一张图片、一个网络帖子等。你给实体一个唯一的标识符 (
PRIMARY KEY
) 以便每个人都可以轻松地引用它。在表格中,您有一个可打印的名称、一个位置、一个“点赞”计数器等。我使用了一个年份表来报告使用适当数量的过滤器可能在该年没有任何结果的情况。客户仍然想查看当年的金额,即使它是零。通过拥有一张年份表,您可以保证每个年份都有一个值。另一种方法是进行外部连接,我认为这会因需要更多扫描而影响性能。
您的用例可能会有所不同,但这并不总是一个坏主意
作为一个快速的答案,我会说你正在使用一个数字来关联另一个数字——而且只有那个(那个年份表中没有额外的价值)。
然后,正如您已经说过的,查询多年将需要额外的努力(连接、子查询等)。