这是好的数据库规范化吗?

时间:2011-07-26 07:34:50

标签: mysql sql database-normalization join

我是使用mysql的初学者,我正在努力学习最佳实践。我已经设置了类似的结构,如下所示。

(包含所有唯一条目的主表) TABLE ='main_content'

+------------+---------------+------------------------------+-----------+
| content_id |  (deleted)    | title                        | member_id | 
+------------+---------------+------------------------------+-----------+
|          6 |               | This is a very spe?cal t|_st |      1    |
+------------+---------------+------------------------------+-----------+ 

(提供每个难度和加入ID的总和 - >实际名称) TABLE ='难度'

+---------------+-------------------+------------------+
| difficulty_id | difficulty_name   | difficulty_total |
+---------------+-------------------+------------------+
|             1 | Absolute Beginner |                1 |
|             2 | Beginner          |                1 | 
|             3 | Intermediate      |                0 |
|             4 | Advanced          |                0 |
|             5 | Expert            |                0 |
+---------------+-------------------+------------------+

(此表确保可以为每个条目插入多个值。例如,        此特定条目表明提交有2个困难) TABLE ='lookup_difficulty'

+------------+---------------+
| content_id | difficulty_id |
+------------+---------------+  
|          6 |             1 |
|          6 |             2 |
+------------+---------------+

我将所有这些加入到一个可读的查询中:

SELECT group_concat(difficulty.difficulty_name) as difficulty, member.member_name
FROM main_content
INNER JOIN difficulty ON difficulty.difficulty_id 
IN (SELECT difficulty_id FROM main_content, lookup_difficulty WHERE lookup_difficulty.content_id = main_content.content_id )
INNER JOIN member ON member.member_id = main_content.member_id

以上工作正常,但我想知道这是不是很好的做法。我几乎遵循了Wikipedia's Database Normalization example所规定的结构。

当我使用EXPLAIN运行上述查询时,它会说:'使用where;使用连接缓冲区'以及我正在使用2个相关子查询。我没有看到任何方法不使用子查询来实现相同的效果,但是我又是一个菜鸟,所以也许有更好的方法....

2 个答案:

答案 0 :(得分:2)

数据库设计看起来很好 - 关于您的查询,您可以使用以下连接重写它:

SELECT group_concat(difficulty.difficulty_name) as difficulty, member.member_name
      FROM main_content
        INNER JOIN lookup_difficulty ON main_content.id = lookup_difficulty.content_id
        INNER JOIN difficulty ON difficulty.id = lookup_difficulty.difficulty_id
        INNER JOIN member ON member.member_id = main_content.member_id

答案 1 :(得分:1)

如果lookup_difficultycontentdifficulty之间提供了链接,我建议您从difficulty_id表中删除main_content列。由于您可以为每个content_id进行多次查找,因此需要一些额外的业务逻辑来确定要放入difficulty_id表中的main_content(或main_content中的多个条目每个difficulty_id的表,但这违反了规范化实践)。对于前者最大值/最小值/随机值。在任何一种情况下,它都没有多大意义。

除此之外,表格看起来还不错。


<强>更新

看到你更新了表格:)

就像旁注一样。使用IN会降低查询速度(IN会导致表扫描)。在任何情况下,它都是这样,但我确信这些天SQL编译器很好地优化了它。