0

我有 6 张桌子。对于此示例,这些已被简化。

user_items

ID | user_id | item_name | version
-------------------------------------
1  | 123     | test      | 1

data

ID | name | version | info
----------------------------
1  | test | 1       | info

data_emails

ID | name | version | email_id
------------------------
1  | test | 1       | 1
2  | test | 1       | 2

emails

ID | email
-------------------
1  | email@address.com
2  | second@email.com

data_ips

ID | name | version | ip_id
----------------------------
1  | test | 1       | 1
2  | test | 1       | 2

ips

ID | ip
--------
1  | 1.2.3.4
2  | 2.3.4.5

我希望实现的目标如下。

用户 (123) 拥有名为“test”的项目。这是给定条目所需的基本信息。

我们的“数据”表中有数据,当前版本为 1,因此我们的 user_items 表中的版本也是 1。这两个表通过名称和版本链接在一起。设置是这样的,因为用户可能有一个我们没有数据的项目,同样可能有一个我们有数据但没有用户拥有的项目..

对于每个项目,还有 0 个或多个相关联的电子邮件和 ips。对于许多项目,这些可能是相同的,因此我们有 data_emails 和 data_ips 表,它们根据 email_id/ip_id 和相应的 ID 列分别链接到 emails 和 ips 表,而不是一遍又一遍地复制实际的 email varchar。

emails 和 ips 通过项目名称和版本号再次与数据版本相关联。

我的第一个查询是这是一个很好/优化良好的数据库设置吗?

我的下一个查询和主要问题是加入这个复杂的数据结构。

我所拥有的是:

PHP
- get all the user items
- loop through them and get the most recent data entry (if any)
- if there is one get the respective emails
- get the respective ips

根据用户项目的数量,这算作 3 个查询还是基本上无限?

我相信上述方法效率低下,因此我想将我的设置压缩为使用一个查询来获取相同的数据。

我通过以下代码实现了这一点

SELECT user_items.name,GROUP_CONCAT( emails.email SEPARATOR ',' ) as emails, x.ip

FROM user_items

JOIN data AS data ON (data.name = user_items.name AND data.version = user_items.version)

LEFT JOIN data_emails AS data_emails ON (data_emails.name = user_items.name AND data_emails.version = user_items.version)

LEFT JOIN emails AS emails ON (data_emails.email_id = emails.ID)

LEFT JOIN
     (SELECT name,version,GROUP_CONCAT( the_ips.ip SEPARATOR ',' ) as ip FROM data_ips
     LEFT JOIN ips as the_ips ON data_ips.ip_id = the_ips.ID  ) 
     x ON (x.name = data.name AND x.version = user_items.version)

为了达到这一点,我做了很多阅读,并且不知疲倦地工作到这里。这可以按我的要求工作 - 这个问题旨在澄清使用它的好处是什么?

我不得不使用子查询(我相信?)来获取 ips,因为以前它是乘以结果(我相信基于复杂的连接)。我想这个子查询的工作原理是我的主要困惑。

问题总结。

- 我的数据库设置是否适合我的使用?任何改进将不胜感激。任何有助于我扩展知识的有用资源都会很棒。

- 我的 sql 中的子查询实际上是如何工作的 - 查询在做什么?

- 我是否正确继续使用左连接 - 我想返回用户项目,如果适用于右边,则返回空值。

- 我是否实质上用 2 替换了可能无限数量的查询?这真的有什么不同吗?以上可以改进吗?

- 鉴于当我更新数据表中某个项目的版本时,我知道必须更新 user_items 表中的版本,我现在还有一些更新查询要做。在实践中这种设置的权衡是否值得?

感谢任何帮助我更好地掌握这一点的人!

4

1 回答 1

0

鉴于您的数据布局和目标,查询是正确的。如果您只有少量数据,那不应该是性能问题 - 随着数据量的增长,这将迅速改变。但是,当您拥有大量数据时,在极少数情况下您应该一次性查看所有数据,这意味着将以某种方式过滤结果。究竟如何过滤它们对查询的结构有巨大的影响。

我的 sql 中的子查询实际上是如何工作的

目前它不能正常工作 - 没有 GROUP BY

在实践中这种设置的权衡是否值得?

否 - 这意味着您的架构过于规范化。

于 2013-04-09T18:42:34.300 回答