我有 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 表中的版本,我现在还有一些更新查询要做。在实践中这种设置的权衡是否值得?
感谢任何帮助我更好地掌握这一点的人!