当用户和设备存储在同一个表中时,SQL / SQLite检索属于用户的设备列表,其中关联存储在另一个表

时间:2018-01-09 17:31:51

标签: sql sqlite join recursion

另一个案例是给出一个设计糟糕,相当古老的数据库并被告知要从中提取有用的信息。我确实讲了很多SQL,但这超出了我的知识。坦率地说,我碰壁了。

所以我给了一个包含几个表的SQLite DB。有趣的是表格节点关联

节点包含所有元素,例如用户,设备(PC),但更多诸如桌面电话设备,办公室电话号码,操作系统,基本上所有内容和任何内容。这是一个样本:

id       title          entity_type
-----------------------------------
1        user1          User
2        user2          User
3        pc1            Device
4        user3          User
5        pc2            Device
6        pc3            Device
7        pc4            Device
8        os1            OS
9        phon1          Phone
10       os2            OS
11       phon2          Phone
11       phon3          Phone

关联将设备映射到用户,但还包含更多垃圾映射,例如PC操作系统,办公室电话等。

id       parent         child
-----------------------------
1        3              1
2        5              2
3        6              4
4        7              4
5        3              8
6        5              8
7        6              10

所以关联将pc1与user1,pc2与user2,pc3和pc4与user3映射,还将os1映射到pc1和pc2,os2到pc3等。 值得庆幸的是,用户只有PC ,没有其他项目映射到用户。

我被要求编制一个列表,显示所有PC以及分配给他们的用户。基本上我需要得到:

user1     pc1
user2     pc2
user3     pc3
user3     pc4

我的想法是:

SELECT nodes.id,title,parent
  FROM nodes
  INNER JOIN associations ON nodes.id = associations.child
  WHERE entity_type = "User"
  ORDER BY id;

到目前为止,这为我提供了所有用户以及属于他们的父母(例如,节点中的PC ID)的列表。我不知道如何替换父,我现在只是一个数字,引用节点中的ID,并带有此项的标题。

任何帮助?

2 个答案:

答案 0 :(得分:0)

您需要对同一个表使用多个连接 - 例如:

select user.title as user, pc.title as pc
from nodes as user
join associations as a on a.child=user.id
join nodes as pc on a.parent=pc.id
where user.entity_type = 'User'

关于评论中提到的“笔记本的父母+ 1”逻辑:如果我理解正确,当PC的标题是“移动”时,它是一个笔记本,下一个id的节点是真实标题。

select user.title as user, ifnull(nb.title, pc.title) as computer
from nodes as user
join associations as a on a.child=user.id
join nodes as pc on a.parent=pc.id
left join nodes as nb on pc.title='mobile' and nb.id = pc.id + 1
where user.entity_type = 'User'

使用left join表示如果电脑标题'移动',则nb字段全部为null,并在填充时填充ifnull是。 select中的Rng.Value2 = Replace(Rng.Value2, Left(Rng.Value2, I - 1), "") 应确保每行都使用正确的标题。

答案 1 :(得分:0)

这是一个将提取所有用户与节点关系的查询。它并不假设用户只是子节点:

$groups = [];
foreach($arr as $val) {
    $groups[] = ['first_key_name' => $val->ID, 'second_key_name' => $val->login];
}