php - 如何在 PHP 中列出来自 MySQL 的规范化数据?

标签 php sql mysql database-design normalization

我总是在处理标准化数据以及如何显示它方面遇到困难。也许是因为我不完全理解规范化规则,比如如何将其完全纳入Boyce-Codd。在这个阶段,性能并不是真正的问题,尽管架构的可维护性才是问题。

用户

ID  Name
1   Alice
2   Bob
3   Charlie

技能

ID   Name
1    Karate
2    Marksmen
3    Cook

事件

ID   Name
1    Island
2    Volcano

用户 m2m 技能

MemberID  SkillID
1         1
1         2
2         1
2         3
3         1

用户 m2m 事件

MemberID  EventID
1         1
1         2
2         1
3         2

如何从数据库中获取此信息?我想显示一个像这样的表格,其中包含每种技能的总数:

事件技能

Event    Karate Marksmen Cook
Island   2      1        1
Volcano  2      1        0

技能表不太可能发生太大变化。这意味着我可以执行一组像这样的子查询(明显缩短且语法不正确)

SELECT event.name,
  (SELECT COUNT(*) FROM ... WHERE skill = 'Karate'), 
  (SELECT COUNT(*) FROM ... WHERE skill = 'Marksmen') FROM event

这就是我一直在做的事情,将其放入 View 中。但这有点可怕,不是吗?每次添加新技能时,我都必须编辑 View 。

客户端处理它的另一种方法。所以我只是得到这样的结果:

Event   Skill    Count
Island  Karate   2
Island  Marksmen 1
Island  Cook     1
Volcano Karate   2
Volcano Marksmen 1

我循环遍历结果,重新格式化它。但我更讨厌这样。数据库不就是用来做数据的吗?

那么:我做错了什么?我是不是期待太多了?哪个是较小的罪恶?

(正如 b3ta 所说,对于帖子的长度和错误的标记表示歉意。:( )

最佳答案

这是一个典型的数据透视查询,因为您希望将行中的数据转换为列。

   SELECT e.name,
          MAX(CASE WHEN x.skill_name = 'Karate' THEN x.num_skill ELSE 0) END AS Karate,
          MAX(CASE WHEN x.skill_name = 'Marksmen' THEN x.num_skill ELSE 0 END) AS Marksmen
     FROM EVENT e
LEFT JOIN (SELECT um.eventid,
                  s.name AS skill_name,
                  COUNT(*) 'num_skill'
             FROM SKILLS s
             JOIN USER-M2M-SKILL us ON us.skillid = s.id
             JOIN USER-M2M-EVENT um ON um.memberid = us.memberid
         GROUP BY um.eventid, s.name) x ON x.eventid = e.id
 GROUP BY e.name

后续问题:

...what does this have that a load of sub queries doesn't?

SELECT 作为 SELECT 子句中的语句。 IE:

SELECT x.name,
       (SELECT COUNT(*) FROM TABLE)

...意味着对每个技能运行单独的查询。如果查询是相关的 - 如果它们通过 ID 绑定(bind)在一起以确保记录与事件同步,则将为每个事件运行计数。

后续结论

这种方法效率极低。最好一次获取必要的值,正如我在答案中提供的那样。

附录

关于更新查询 - 通过使用动态 SQL 实现查询可以最大限度地减少维护。

关于php - 如何在 PHP 中列出来自 MySQL 的规范化数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1931550/

相关文章:

javascript - jquery将表单和变量放在一起

php - 如何调用 PHP 动态变量名?

php - 支持 xdebug 的 Linux 轻量级 PHP 编辑器或 IDE

mysql - SQL : how to select different rows where values are equal to an set of values?

c# - 使用 LINQ to SQL 的简单 LINQ 查询,认为我做错了什么

mysql - 无法处理 MySQL FULL JOIN 查询

PHP ImagickException : not authorized

sql - SQL Server 数据库 'optimizing' 索引的奇怪结果,原因是什么?

mysql - 在 MySQL 中索引只有一列的表的性能

php - 如何替换/加速使用 LIKE 的文本搜索查询?