GROUP CONCAT 和 LEFT OUTER JOIN 拆分
GROUP CONCAT and LEFT OUTER JOIN to split
我正在与 SQL Workbench 合作。这是我的表格示例:
SITES
id
BUILDINGS
id
site_id
LEVELS
id
building_id
我没有创建这个数据库,也不能修改它。每个建筑物对应一个站点,因此它包含该站点的 KEY。与关卡和建筑物相同。
我正在尝试得到这个结果
site_id | buildings_id | levels_id
1 | 15, 16 | (213, 214), (313, 314)
2 | 21, 22, 23 | (350), (400, 401, 402), (501)
3 | 31, 32, 33, 34 | (5001, 5002), (7001), (8009), (8400)
前两列很简单,但我对第三列有疑问。括号是说明性的,我不一定需要那些。但我需要一种方法将字符串拆分为 building_id.
每个 (...) 对应一栋建筑物的楼层。
这是我现在正在处理的查询,return是第一列和第二列。我尝试向查询中添加另一个 LEFT OUTER JOIN,但没有成功。我尝试了很多东西,但我尝试的大多数东西 return 错误或奇怪的输出。
SELECT
sites.id AS site_id,
GROUP_CONCAT(DISTINCT buildings.id
SEPARATOR '; ') AS buildings_id
FROM
sites
LEFT OUTER JOIN
users_has_sites ON users_has_sites.sites_id = sites.id
LEFT OUTER JOIN
users ON users.id = users_has_sites.users_id
LEFT OUTER JOIN
buildings ON buildings.sites_id = sites.id
WHERE
users.id = 42
GROUP BY site_id;
感谢任何帮助。谢谢
根据您的要求和table结构推断 你可以试试这个 sql
SELECT site.id,GROUP_CONCAT(c.building_id) building_id,GROUP_CONCAT(c.level_id) levels_id
从网站,(
SELECT building.site_id,building.id building_id,
concat('(',GROUP_CONCAT(level
.id),')') level_id
来自大楼,level
WHERE building.id = level
.building_id GROUP BY building.id
) c 其中 site.id = c.site_id
分组 site.id;
您需要两个聚合级别:一个是 building_id
,另一个是 site_id
。
with b_l as ( select b.id as building_id , b.site_id , concat('(' , group_concat( l.id order by l.id separator ',' ) , ')' ) as building_levels from buildings as b left join levels as l on b.id = l.building_id group by b.id, b.site_id ) , s_b as ( select s.id , group_concat( b_l.building_id order by b_l.building_id separator ',' ) as buildings , group_concat( b_l.building_levels order by b_l.building_id separator ',' ) as levels from sites as s left join b_l on s.id = b_l.site_id group by s.id ) select * from s_b
id | buildings | levels -: | :-------- | :---------------------- 1 | 1,2,3 | (1,2),(3,4,5),(6) 2 | 4,5,6 | (7,8),(9),(10,11) 3 | 7,8,9 | (12,13,14),(15,16),(17) 4 | 10 | null
或与横向连接相同:
select s.id , group_concat( b_l.building_id order by b_l.building_id separator ',' ) as buildings , group_concat( b_l.building_levels order by b_l.building_id separator ',' ) as levels from sites as s left join lateral ( select b.site_id , b.id as building_id , concat('(' , group_concat( l.id order by l.id separator ',' ) , ')' ) as building_levels from buildings as b left join levels as l on b.id = l.building_id group by b.id, b.site_id ) b_l on s.id = b_l.site_id group by s.id
db<>fiddle here
您可以使用两个级别的聚合,从最低级别开始:
SELECT site_id,
GROUP_CONCAT(building_id ORDER BY building_id SEPARATOR ', ') as building_ids,
GROUP_CONCAT('(', levels, ')' ORDER BY building_id SEPARATOR ', ') as levels
FROM (SELECT s.id AS site_id, b.id as building_id,
GROUP_CONCAT(l.id ORDER BY l.id SEPARATOR ', ') as levels
FROM sites s LEFT JOIN
users_has_sites uhs
ON uhs.sites_id = s.id LEFT JOIN
buildings b
ON b.sites_id = s.id LEFT JOIN
levels l
ON l.building_id = b.id
WHERE uhs.users_id = 42
GROUP BY site_id, b.id
) sb
GROUP BY site_id;
请注意,users
table 不是必需的,因为 id 在联结点 table 中。此外,可能不需要 sites
但您将其用于 LEFT JOIN
(尽管 WHERE
子句将其转换为 INNER JOIN
)。不过我把它留在里面了。