进行这种递归多对多数据库查找的最优雅方法是啥?
Posted
技术标签:
【中文标题】进行这种递归多对多数据库查找的最优雅方法是啥?【英文标题】:What's the most elegant way to do this recursive many-to-many database lookup?进行这种递归多对多数据库查找的最优雅方法是什么? 【发布时间】:2013-07-31 01:28:07 【问题描述】:我有一个 mysql 表,其中包含有关用户的多对多数据:
username (PK) ip (PK) machine_id (PK)
--------------------------------------------------
tester1 1.2.3.4 ABC
tester1 6.6.6.6 BBB
tester2 1.2.3.4 ZZZ
tester3 2.3.4.5 ABC
tester4 2.3.4.5 OOO
tester5 1.2.3.4 XYZ
tester5 8.9.7.6 BBB
tester5 1.2.3.4 OOO
tester6 9.9.9.9 ZZZ
它使用组合主键将行限制为所有三列的唯一组合。
如您所见,同一用户可以使用多个 IP 地址和多台机器的组合来访问系统。就我而言,如果他们具有相同的 IP 或机器 ID,则它们是同一用户。
我想要一种方法来查找数据之间所有可能的连接,以便我可以识别某人使用过的用户名/IP/ID 的每个可能组合。
示例
如果我想知道 tester1 使用了哪些别名,这很简单:SELECT * FROM users WHERE username LIKE '%tester1%'
这会给我:
tester1 1.2.3.4 ABC
tester1 6.6.6.6 BBB
然后我可以将 IP 1.2.3.4 和 6.6.6.6 与该用户连接,如果我查看这两个 IP,我可以看到它们使用了一些其他名称和机器 ID:
tester2 1.2.3.4 ZZZ
tester5 1.2.3.4 XYZ
tester5 1.2.3.4 OOO
tester1 6.6.6.6 BBB
然后我继续查找用户的所有机器 ID,这为我们提供了他的另一个别名(来自机器 ID OOO
):
tester4 2.3.4.5 OOO
查找OOO
我又找到了另一个IP,2.3.4.5,它给了我另一个连接:
tester3 2.3.4.5 ABC
由于我们之前查过机器IDABC
,所以不需要再查了。
我现在已经确定了该用户所有可能的别名,并且拥有了他使用的 IP、机器 ID 和用户名的完整列表。所有这些都来自递归查找数据,然后对其结果进行另一个递归查找,依此类推。
我的问题是,如何将此逻辑转换为 php/SQL?
有没有办法通过查询直接提取所有“连接”的数据,或者是否需要一些 PHP 处理,如果需要,怎么办?
【问题讨论】:
mysql 不进行递归查询。您可以通过进行一系列自连接来“伪造”它,但这仅适用于一定的“递归”深度,它不会一直持续下去。它也很快变得非常丑陋。所以,是的……需要客户端处理。 我是这么认为的。我只是停留在 PHP 的逻辑上。 基本上是一个 while() 循环,它会不断深入挖掘,直到你到达树的底部(或顶部)。 您还可以通过调用填充临时表的递归存储过程(例如the one proposed in this other anwser)来模拟递归查询。从理论上讲,这应该比从 PHP 中重复查询要快,但写起来也有点痛苦。 【参考方案1】:基本上,您可以在机器 id 列上使用选择查询和 2 个自连接。例如:
select * from users left join users u1 on users. mid=u1.mid left join users u2 on u1. mid=u2. mid where name like "%tester1%"
【讨论】:
以上是关于进行这种递归多对多数据库查找的最优雅方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章