通过外键实现更简单的通用查询的冗余?

问题描述 投票:0回答:1

我很想将外键添加到不需要它的表中,只是为了简化常见查询。事情会那么糟糕吗?

下面是一个简化的示例,以说明我正在处理的内容。

CREATE TABLE group
(
    group_id INT AUTO_INCREMENT NOT NULL,
    group VARCHAR(32) NOT NULL,
    PRIMARY KEY (group_id),
)

CREATE TABLE item
(
    item_id INT AUTO_INCREMENT NOT NULL,
    item VARCHAR(32) NOT NULL,
    PRIMARY KEY (item_id),
    FOREIGN KEY (group_id) REFERENCES group(group_id)
)

CREATE TABLE order
(
    order_id INT AUTO_INCREMENT NOT NULL,
    order VARCHAR(32) NOT NULL,
    PRIMARY KEY (order_id),
    FOREIGN KEY (item_id) REFERENCES item(item_id)
-- FOREIGN KEY (group_id) REFERENCES item(group_id) <- not needed,  but...
)

从逻辑的角度来看,这种结构是所需要的,但是我知道查询订单表有两种常见的模式:

  1. 按item_id
  2. 通过group_id

在第二种情况下,查询应类似于:

with merged as
(
    SELECT *
    FROM item JOIN group
      ON item.group_id = group.group_id
)

SELECT *
FROM order JOIN merged
  ON order.item_id = merged.item_id
WHERE merged.group = 'my_group'

如果我添加group_id作为外键是为了添加一些冗余(浪费一些空间),但是我可以减少用户两次加入的需要。

此外,我仅80%地确定db优化器可以确保查询具有相同的性能(从技术上讲,它不能具有相同的性能,但是应该具有相似的性能)。

sql database database-normalization
1个回答
0
投票

首先,grouporder是SQL中的关键字。这使得它们对于表名而言确实是很糟糕的候选者。我将表名设为复数的原因之一是因为它避免了与大多数关键字的冲突。

第二,使用外键关系描述数据的结构。您可以添加其他索引来提高性能。

第三,您需要声明列以在约束中使用它们。

您似乎想要:

CREATE TABLE groups (
    group_id INT AUTO_INCREMENT NOT NULL,
    group VARCHAR(32) NOT NULL,
    PRIMARY KEY (group_id)
);

CREATE TABLE items (
    item_id INT AUTO_INCREMENT NOT NULL,
    item VARCHAR(32) NOT NULL,
    group_id int,
    PRIMARY KEY (item_id),
    FOREIGN KEY (group_id) REFERENCES group(group_id)
)

CREATE TABLE orders (
    order_id INT AUTO_INCREMENT NOT NULL,
    order VARCHAR(32) NOT NULL,
    item_id INT,
    PRIMARY KEY (order_id),
    FOREIGN KEY (item_id) REFERENCES item (item_id)
);

项目成组,订单中有项目。您尚未描述group_id中是否需要orders。您可以通过item_id查找它。不要存储冗余信息。

当然,如果order可以与group分开具有item,则另外的group_id列就有意义。

© www.soinside.com 2019 - 2024. All rights reserved.