1

我有以下关于 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

提前致谢!

编辑:

我喜欢拥有真正连续的位置序列,其中只有从下一次访问时间中多次出现的相同位置应该被分组。

编辑2:

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

例如:用户 1 从 A 移动到 B,他在 B 停留了超过 1 个条目:B,B,然后他回到 A,之后他去了 C。

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

从 A 到 B 到 A 到 C

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

4

4 回答 4

2

这是语法:

Select group_concat(distinct position order by position)
from Table
where userId=1
于 2013-06-07T11:08:45.677 回答
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
于 2013-06-07T11:46:44.293 回答
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()不是编写上述怪物......

于 2013-06-07T11:28:40.650 回答
0

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

我建议在您的应用程序层中执行此操作。

于 2013-06-07T11:14:25.900 回答