Group_Concat内部按订单分组

时间:2013-06-07 11:04:48

标签: mysql sql

我有关于GROUP_CONCAT()的以下问题:

我的表格简化了以下格式:

| userId | visitTime | position |
     1       TIME1         A
     1       TIME2         B
     1       TIME3         B
     1       TIME4         B
     1       TIME5         A
     1       TIME6         C

使用我当前的sql语句:

Select group_concat(position) from Table where userId=1

我收到了

A,B,B,B,A,C

如何对group_concat进行分组,以便得到如下结果:

  A,B,A,C

提前致谢!

编辑:

我喜欢拥有真实的连续位置序列,其中只应对下次visitTime中相同位置的多次出现进行分组。

EDIT2:

我的预期输出是 A,B,A,C

例如:用户1从A移动到B, 在那里,他留在B超过1次入场:B,B,而不是他回到A,之后他去了C.

我只想得到他使用的路径:

从A到B到A到C

因此,如果用户移动到另一个位置,则应该识别,但他可以再次移回。

4 个答案:

答案 0 :(得分:2)

以下是语法:

Select group_concat(distinct position order by position)
from Table
where userId=1

答案 1 :(得分:1)

首先,要实现这一点,您需要一个唯一的ID来向您显示记录的顺序(否则您的请求无法实现)。所以我要在你的表中添加id列,如下所示:

| id | userId | visitTime | position |
  1      1       TIME1         A
  2      1       TIME2         B
  3      1       TIME3         B
  4      1       TIME4         B
  5      1       TIME5         A
  6      1       TIME6         C

现在提取最终字符串的查询:

SELECT GROUP_CONCAT(t3.position ORDER BY t3.id)
FROM (
    SELECT t1.*, ((
        SELECT position
        FROM Table
        WHERE
            id > t1.id
        AND
            userId = 1
        ORDER BY id
        LIMIT 1
        )) AS following_position
    FROM Table t1
    WHERE
        t1.userId = 1
) t3
WHERE
    t3.position <> t3.following_position OR t3.following_position IS NULL

这是不使用子查询的相同查询(我期望以这种方式获得更好的性能,但我不确定它中是否有太多的NULL):

SELECT GROUP_CONCAT(t3.position ORDER BY t3.id)
FROM (
    SELECT t1.*, MIN(t2.id) AS following_id
    FROM Table t1
    LEFT JOIN Table t2 ON (t1.id < t2.id)
    WHERE
        t1.userId = 1
    AND
        (t2.userId = 1 OR t2.userId IS NULL)
    GROUP BY t1.id
) t3
LEFT JOIN Table t4 ON (t3.following_id = t4.id)
WHERE
    t3.position <> t4.position OR t4.position IS NULL

答案 2 :(得分:0)

我很确定你找不到一个很好的MySQL解决方案。

我建议你在你的应用层进行。

答案 3 :(得分:0)

尝试此查询(依赖于每个用户的唯一visitTime值...)

-- get those elements p1 from your table...
select p1.userId, group_concat(p1.position order by p1.visitTime)
from p p1
-- for which there doesn't exist a successor p2 with the same "position"
where not exists (
  select *
  from p p2
  where p1.userId = p2.userId
  and p1.visitTime < p2.visitTime
  and p1.position = p2.position
  -- for which there doesn't exist any record p3 strictly in between p1 and p2
  and not exists (
    select *
    from p p3
    where p2.userId = p3.userId
    and p1.visitTime < p3.visitTime
    and p2.visitTime > p3.visitTime
  )
)
group by p1.userId

请参阅此SQLFiddle中的演示。

注意,在其他数据库中,您可能会使用窗口函数,例如LEAD() OVER()LAG() OVER(),而不是编写上面的怪物......