SQL中的标签组

时间:2017-08-05 12:59:17

标签: mysql sql

我有一张这样的表:

id   name
0     Bob
1   Alice
2     Bob
3   
4     Bob
5    Mary
6   Alice

我需要为每个不同的名称分配一个group_id

id   name   group_id
0     Bob          0  -- Bob's group
1   Alice          1  -- Alice's group
2     Bob          0  -- Bob's group
3                     -- no group (NULL)
4     Bob          0  -- Bob's group
5    Mary          2  -- Mary's group
6   Alice          1  -- Alice's group

这可以在MySQL的一行中完成吗?

我知道我可以找到带有自动增量列的唯一名称,然后根据名称加入原始表格 - 但我想知道是否存在更简单/更快的解决方案......

2 个答案:

答案 0 :(得分:1)

是的,用例。只需根据表达式添加一个新的计算列,该表达式为name列的每个字符串值输出适当的值

Select id, name, 
   case name
      when 'Bob' then 0 
      when 'Alice' then 1 
      when 'Mary' then 2 
      -- etc.
      end GroupId
From table 

如果您事先不知道这些名字,或者有太多名字,请试试这个:

Select id, name,
  (select count(distinct name) 
   from table 
   where name < t.Name) groupId
From table t

除非在name列上添加索引,否则在大型表上这将非常慢。

要为name = null的行输出null而不是0,请使用:

Select id, name,
  case when name is null then null 
    else (select count(distinct name) 
          from table 
          where name < t.Name) end groupId
From table t

答案 1 :(得分:0)

一种方法是 - 如您所建议的那样 - group byjoin。如果数字不必是连续的:

select t.*, minid as group_id
from t join
     (select name, min(id) as minid
      from t
      group by name
     ) tt
     on not t.name <=> tt.name;  -- to handle `NULL`

如果有,请使用变量:

select t.*, minid as group_id
from t join
     (select name, min(id) as minid, (@grp := @grp + 1) as group_id
      from t cross join
           (select @grp := -1) params
      group by name
     ) tt
     on not t.name <=> tt.name;  -- to handle `NULL`;

您还可以使用两种排序和变量执行整个操作:

select t.*
from (select t.*,
             (@grp := if(not @n <=> name, @grp,
                         if(@n := name, 1, 1)
                        )
             ) as group_id
      from t
           (select @grp := -1, @n := '') params
      order by name
     ) t
order by id;