Mysql Split String和Select with results

时间:2015-05-06 08:39:32

标签: mysql string select split

我目前有2张表格如下:

frontend_users:
uid | usergroup | name
1   | 1,2,3     | Michael
2   | 2         | Tobias
3   | 1         | Colin
...

usergroups:
uid | title
1   | member
2   | reporter
3   | admin

我尝试拆分用户组并为每个数字选择用户组并将其添加到显示结果中,在最佳情况下应如下所示:

uid | name    | groups
1   | Michael | member, reporter, admin
2   | Tobias  | reporter
3   | Colin   | member

我到目前为止找到的最好结果是从这里: Split String and Do Calculation in MySQL 但我似乎无法从substring_index结果中选择其他表。 我当前的查询如下所示:

SELECT frontend_users.uid, frontend_users.name
CASE
    WHEN frontend_users.usergroup LIKE '%,%,%' THEN
        CONCAT((SELECT usergroups.title FROM usergroups, frontend_users WHERE usergroups.uid = SUBSTRING_INDEX(frontend_users.usergroup, ',', 1)),
            (SELECT usergroups.title FROM usergroups, frontend_users WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(frontend_users.usergroup, ',', 2), ',', -1)),
            (SELECT usergroups.title FROM usergroups, frontend_users WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(frontend_users.usergroup, ',', 3), ',', -1)))       
    WHEN frontend_users.usergroup LIKE '%,%' THEN
        CONCAT((SELECT usergroups.title FROM usergroups, frontend_users WHERE usergroups.uid = SUBSTRING_INDEX(frontend_users.usergroup, ',', 1)),
            (SELECT usergroups.title FROM usergroups, frontend_users WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(frontend_users.usergroup, ',', 2), ',', -1))),
    ELSE (SELECT usergroups.title FROM usergroups, frontend_users WHERE usergroups.uid = frontend_users.usergroup)
END AS groups
FROM frontend_users, usergroups

我尝试使用for循环来获得组数,但结果更糟。

有关如何将select查询与substring_index结果一起使用的任何提示吗?

2 个答案:

答案 0 :(得分:1)

你应该考虑规范化。但是对于当前架构,请考虑以下

mysql> select * from frontend_users ;
+------+-----------+---------+
| uid  | usergroup | name    |
+------+-----------+---------+
|    1 | 1,2,3     | Michael |
|    2 | 2         | Tobias  |
|    3 | 1         | Colin   |
+------+-----------+---------+
3 rows in set (0.00 sec)

mysql> select * from usergroup ;
+------+----------+
| uid  | title    |
+------+----------+
|    1 | member   |
|    2 | reporter |
|    3 | admin    |
+------+----------+
3 rows in set (0.00 sec)

要获得所需的结果,您可以使用以下查询,该查询对长期运行效率不高

select 
u.uid,
u.name, 
group_concat(g.title) as groups 
from frontend_users u 
join usergroup g on find_in_set(g.uid,u.usergroup) > 0 
group by u.uid ;

+------+---------+-----------------------+
| uid  | name    | groups                |
+------+---------+-----------------------+
|    1 | Michael | admin,reporter,member |
|    2 | Tobias  | reporter              |
|    3 | Colin   | member                |
+------+---------+-----------------------+

现在更好的方法是创建一个关联表作为

mysql> create table user_to_group (uid int, gid int);
Query OK, 0 rows affected (0.15 sec)

mysql> insert into user_to_group values (1,1),(1,2),(1,3),(2,2),(3,1);
Query OK, 5 rows affected (0.02 sec)
Records: 5  Duplicates: 0  Warnings: 0

更好的查询将是

select 
u.uid,
u.name, 
group_concat(g.title) as groups 
from frontend_users u 
join user_to_group ug on ug.uid = u.uid 
join usergroup g on g.uid = ug.gid 
group by u.uid ;

+------+---------+-----------------------+
| uid  | name    | groups                |
+------+---------+-----------------------+
|    1 | Michael | member,admin,reporter |
|    2 | Tobias  | reporter              |
|    3 | Colin   | member                |
+------+---------+-----------------------+

答案 1 :(得分:0)

Abhik Chakraborty答案是更好的解决方案,但我只是修改你的最后一个代码,如果你愿意的话。

您可以在fiddle

查看
SELECT frontend_users.uid, frontend_users.name,
CASE
    WHEN usergroup LIKE '%,%,%' THEN
        CONCAT(
           (
             SELECT title FROM usergroups
             WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(usergroup, ',', 1), ',', -1)
           )
          ,',',
           (
              SELECT title FROM usergroups
              WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(usergroup, ',', 2), ',', -1)
            )
          ,',',
           (
              SELECT title FROM usergroups
              WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(usergroup, ',', 3), ',', -1)
            )
          )
    WHEN usergroup LIKE '%,%' THEN
        CONCAT(
           (
             SELECT title FROM usergroups
             WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(usergroup, ',', 1), ',', -1)
           )
          ,',',
           (
              SELECT title FROM usergroups, frontend_users
              WHERE usergroups.uid = SUBSTRING_INDEX(SUBSTRING_INDEX(usergroup, ',', 2), ',', -1) Limit 1
            )
          )
    ELSE
        (SELECT title FROM usergroups, frontend_users WHERE usergroups.uid = usergroup Limit 1)
END AS groups
FROM frontend_users