Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql SQL中分区上的字符串Concat?_Mysql_Sql_Window Functions - Fatal编程技术网

Mysql SQL中分区上的字符串Concat?

Mysql SQL中分区上的字符串Concat?,mysql,sql,window-functions,Mysql,Sql,Window Functions,我想连接周围的行在以下示例中,只有在排名到新columngroup by后周围的2行似乎不起作用,以下是我的数据: 模式MySQL v8.0 来说明我想做什么。我可以使用sum子句对数值求和,如下所示: 问题1 用户id 日期和时间 事件名称 不重要的 琐碎的新 001 2020-12-10 10:00:00 A. 1. 13 001 2020-12-10 10:00:01 B 9 19 001 2020-12-10 10:00:02 C 3. 21 001 2020-12-10 10:00:2

我想连接周围的行在以下示例中,只有在排名到新columngroup by后周围的2行似乎不起作用,以下是我的数据:

模式MySQL v8.0

来说明我想做什么。我可以使用sum子句对数值求和,如下所示: 问题1

用户id 日期和时间 事件名称 不重要的 琐碎的新 001 2020-12-10 10:00:00 A. 1. 13 001 2020-12-10 10:00:01 B 9 19 001 2020-12-10 10:00:02 C 3. 21 001 2020-12-10 10:00:20 D 6. 20 001 2020-12-10 10:00:40 E 2. 11 002 2020-12-10 10:00:02 A. 2. 15 002 2020-12-10 10:00:09 B 4. 15 002 2020-12-10 10:00:10 C 9 15 002 2020-12-10 10:00:50 D 0 13
您可以通过使用CTEs来解决这个问题:首先计算每个用户id的行号,按日期和时间排序;然后根据行号在该行的最小/最大行号范围内(从行号-之前到行号+之后)将表连接到自身。然后,您可以从联接表中的“事件名称”字段对\u conc进行分组:

设置@before:=2; 设置@after:=2; 以rns为例 选择*, 按用户id划分的卡斯特罗\u编号按日期\u时间排序,签名为rn 从log_表 选择r1.user\u id、r1.date\u time、r1.event\u name、, 组\u CONCATr2.event\u名称分隔符作为事件\u名称\u新建 来自rns r1 在r2.user\u id=r1.user\u id上加入rns r2 r2.rn介于r1.rn-@之前和r1.rn+@之后 按r1.user\u id、r1.date\u time、r1.event\u name分组 按r1.user\U id订购,r1.rn 2之前和2之后的输出:

user_id     date_time               event_name  event_name_new
001         2020-12-10 10:00:00     a           abc
001         2020-12-10 10:00:01     b           abcd
001         2020-12-10 10:00:02     c           abcde
001         2020-12-10 10:00:20     d           bcde
001         2020-12-10 10:00:40     e           cde
002         2020-12-10 10:00:02     A           ABC
002         2020-12-10 10:00:09     B           ABCD
002         2020-12-10 10:00:10     C           ABCD
002         2020-12-10 10:00:50     D           BCD

您可以通过使用CTEs来解决这个问题:首先计算每个用户id的行号,按日期和时间排序;然后根据行号在该行的最小/最大行号范围内(从行号-之前到行号+之后)将表连接到自身。然后,您可以从联接表中的“事件名称”字段对\u conc进行分组:

设置@before:=2; 设置@after:=2; 以rns为例 选择*, 按用户id划分的卡斯特罗\u编号按日期\u时间排序,签名为rn 从log_表 选择r1.user\u id、r1.date\u time、r1.event\u name、, 组\u CONCATr2.event\u名称分隔符作为事件\u名称\u新建 来自rns r1 在r2.user\u id=r1.user\u id上加入rns r2 r2.rn介于r1.rn-@之前和r1.rn+@之后 按r1.user\u id、r1.date\u time、r1.event\u name分组 按r1.user\U id订购,r1.rn 2之前和2之后的输出:

user_id     date_time               event_name  event_name_new
001         2020-12-10 10:00:00     a           abc
001         2020-12-10 10:00:01     b           abcd
001         2020-12-10 10:00:02     c           abcde
001         2020-12-10 10:00:20     d           bcde
001         2020-12-10 10:00:40     e           cde
002         2020-12-10 10:00:02     A           ABC
002         2020-12-10 10:00:09     B           ABCD
002         2020-12-10 10:00:10     C           ABCD
002         2020-12-10 10:00:50     D           BCD

相关子查询可能是最简单的解决方案:

with l as (
      select l.*,
             cast(row_number() over (partition by user_id order by date_time) as signed) as seqnum
      from log_table l
     )
select l.*,
       (select group_concat(l2.event_name order by l2.date_time separator '')
        from l l2
        where l2.user_id = l.user_id and
              l2.seqnum between l.seqnum - 2 and l.seqnum + 2
       ) as new_event_name
from l;
如果事件名称为一个字符,则可以消除相关子查询并使用字符串操作:

with l as (
      select l.*, full_concat,
             cast(row_number() over (partition by user_id order by date_time) as signed) as seqnum
      from log_table l join
           (select user_id,  group_concat(event_name order by date_time separator '') as full_concat
            from log_table l
            group by user_id
           ) ll
           using (user_id)
     )
select l.*, substr(full_concat, greatest(seqnum - 2, 1), least(5, seqnum + 2))
from l;

是一个dbfiddle。

相关子查询可能是最简单的解决方案:

with l as (
      select l.*,
             cast(row_number() over (partition by user_id order by date_time) as signed) as seqnum
      from log_table l
     )
select l.*,
       (select group_concat(l2.event_name order by l2.date_time separator '')
        from l l2
        where l2.user_id = l.user_id and
              l2.seqnum between l.seqnum - 2 and l.seqnum + 2
       ) as new_event_name
from l;
如果事件名称为一个字符,则可以消除相关子查询并使用字符串操作:

with l as (
      select l.*, full_concat,
             cast(row_number() over (partition by user_id order by date_time) as signed) as seqnum
      from log_table l join
           (select user_id,  group_concat(event_name order by date_time separator '') as full_concat
            from log_table l
            group by user_id
           ) ll
           using (user_id)
     )
select l.*, substr(full_concat, greatest(seqnum - 2, 1), least(5, seqnum + 2))
from l;

是一个dbfiddle。

包含您提供的示例数据和预期输出,我不清楚使用滞后有什么问题?@Nick如果sum可以在没有滞后的情况下做到这一点,我想知道是否可以连接字符串?@Nick例如,我想连接周围的5行5行,然后再连接该行5行到新列,我如何才能做到整洁?不幸的是,没有办法要为字符串连接指定窗口函数。。。你能用更复杂的预期输出数据编辑你的问题吗?e、 g.2之前,1之后,这会让你更容易想出一个好主意solution@Nick请检查更新的问题。根据您提供的样本数据和预期输出,我不清楚使用滞后有什么问题?@Nick如果sum可以在没有滞后的情况下做到这一点,我想知道是否可以连接字符串?@Nick例如,我想连接周围的5行5行,然后再连接该行5行到新列,我如何才能做到整洁?不幸的是,没有办法要为字符串连接指定窗口函数。。。你能用更复杂的预期输出数据编辑你的问题吗?e、 g.2之前,1之后,这会让你更容易想出一个好主意solution@Nick请检查更新的问题。它对我来说太复杂了,让我花些时间来消化它。你能解释一下吗?例如,代码中的一些注释。@LernerZhang看一看,它显示了中间CTE的输出,以及如果去掉分组,从最终查询中得到的结果。那可能会有帮助…@LernerZhang我得走了。。。请在评论中留下任何问题,我会尽快回答。@LernerZhang睡过觉后,我意识到这个问题可以简化。请查看我的编辑。@LernerZhang是的,不再需要计数*,这是原始查询的一部分,在我编辑后不再需要。我已经把它从答案中删除了。您确实需要ORDERBY子句中的r1.rn,否则这些行不会按日期\时间排序。这对我来说太复杂了,让我花一些时间来消化它。你能请求吗
你能解释一下吗?例如,代码中的一些注释。@LernerZhang看一看,它显示了中间CTE的输出,以及如果去掉分组,从最终查询中得到的结果。那可能会有帮助…@LernerZhang我得走了。。。请在评论中留下任何问题,我会尽快回答。@LernerZhang睡过觉后,我意识到这个问题可以简化。请查看我的编辑。@LernerZhang是的,不再需要计数*,这是原始查询的一部分,在我编辑后不再需要。我已经把它从答案中删除了。您确实需要ORDERBY子句中的r1.rn,否则这些行不会按日期\时间排序