如何遍历MySQL中的行并根据下一行的值插入数据?

时间:2017-06-29 22:36:01

标签: mysql sql mysql-workbench

这是我在MySQL中的现有表

name  UUID  date_time             org_id
SK    null  2017-04-19 01:36:34    2
SK    null  2017-04-19 01:36:53    2
SK    null  2017-04-19 01:37:23    2
TK    null  2017-02-11 01:37:20    5
TK    null  2017-02-11 01:37:31    5
KK    null  2017-01-01 11:37:33    1

我想更新表并根据名称是否相同以及时间戳是否在1分钟之内插入一个唯一的UUID而不是null,并且org_id在SQL中是相同的。

期望的输出:

name  UUID  date_time             org_id
SK    we23  2017-04-19 01:36:34    2
SK    we23  2017-04-19 01:36:53    2
SK    we23  2017-04-19 01:37:23    2
TK    rt56  2017-02-11 01:37:20    5
TK    rt56  2017-02-11 01:37:31    5
KK    yu77  2017-01-01 11:37:33    1

请告诉我如何使用MySQL workbench编写SQL脚本来实现此目的..

2 个答案:

答案 0 :(得分:1)

你可以用MySQL来做,但是相当复杂,因为它需要几个子查询。

SELECT
    name, date_time, org_id, uuid
FROM
    (
        SELECT
            `name`, `date_time`, `org_id`, 
            (SELECT 
                sum(step) 
             FROM
             (
                  SELECT
                      t1.`name`, t1.`date_time`, t1.`org_id`,
                      case when exists 
                        (SELECT 1
                         FROM t AS t2 
                         WHERE t2.`name` = t1.`name` 
                           AND timestampdiff(second, t1.date_time, t2.date_time) < 60
                           AND t2.date_time > t1.date_time
                           ) 
                      then 0
                      else 1
                      end AS step
                  FROM
                      t AS t1
             ) AS ttt
             WHERE
                ttt.name <= t.name AND ttt.date_time <= ttt.date_time
            ) AS group_number
        FROM
            t
    ) AS ttt2
    JOIN
    (
        SELECT 1 AS group_number, UUID() AS `uuid`
        UNION
        SELECT 2 AS group_number, UUID() AS `uuid`
        UNION
        SELECT 3 AS group_number, UUID() AS `uuid`
        -- and as many as needed
    ) u ON u.group_number = ttt2.group_number
ORDER BY
    name, date_time ;

你会得到:

name | date_time           | org_id | uuid                                
:--- | :------------------ | -----: | :-----------------------------------
KK   | 2017-01-01 11:37:33 |      1 | 636c0fcf-5d3f-11e7-8f8c-00163ebcde7e
SK   | 2017-04-19 01:36:34 |      2 | 636c107a-5d3f-11e7-8f8c-00163ebcde7e
SK   | 2017-04-19 01:36:53 |      2 | 636c107a-5d3f-11e7-8f8c-00163ebcde7e
SK   | 2017-04-19 01:37:23 |      2 | 636c107a-5d3f-11e7-8f8c-00163ebcde7e
TK   | 2017-02-11 01:37:20 |      5 | 636c108d-5d3f-11e7-8f8c-00163ebcde7e
TK   | 2017-02-11 01:37:31 |      5 | 636c108d-5d3f-11e7-8f8c-00163ebcde7e

如果您想要更新,请使用该表格加入原始表格,然后更新。

这可以通过几个步骤完成......首先,您需要订购数据,并确定您需要在哪个时间点更改组&#34; (我称之为step)。这将为您提供一个中间表(ttt):

CREATE TABLE ttt AS
SELECT
    t1.`name`, t1.`date_time`, t1.`org_id`,
    case when 
         exists 
         (SELECT 1
          FROM t AS t2 
          WHERE 
            t2.`name` = t1.`name` 
             AND timestampdiff(second, t1.date_time, t2.date_time) < 60
             AND t2.date_time > t1.date_time
            ) 
    then 0
    else 1
    end AS step
FROM
    t AS t1
ORDER BY
   `name`, `date_time`, `org_id` ;

表ttt是:

name | date_time           | org_id | step
:--- | :------------------ | -----: | ---:
KK   | 2017-01-01 11:37:33 |      1 |    1
SK   | 2017-04-19 01:36:34 |      2 |    0
SK   | 2017-04-19 01:36:53 |      2 |    0
SK   | 2017-04-19 01:37:23 |      2 |    1
TK   | 2017-02-11 01:37:20 |      5 |    0
TK   | 2017-02-11 01:37:31 |      5 |    1

从该表中,对于每一行,计算SUM(all preceding steps)。这是由以下人员完成的:

CREATE TABLE ttt2 AS
SELECT
    `name`, `date_time`, `org_id`, 
    (SELECT 
        sum(step) 
     FROM
        ttt
     WHERE
        ttt.name <= t.name AND ttt.date_time <= ttt.date_time
    ) AS group_number
FROM
    t
ORDER BY
    `name`, `date_time`, `org_id` ;

然后你会得到第二个中间表,我称之为tt2

name | date_time           | org_id | group_number
:--- | :------------------ | -----: | -----------:
KK   | 2017-01-01 11:37:33 |      1 |            1
SK   | 2017-04-19 01:36:34 |      2 |            2
SK   | 2017-04-19 01:36:53 |      2 |            2
SK   | 2017-04-19 01:37:23 |      2 |            2
TK   | 2017-02-11 01:37:20 |      5 |            3
TK   | 2017-02-11 01:37:31 |      5 |            3

现在,您通过加入(1,UID1),(2,UID2)等表来将group_number更改为UUID。元组:

SELECT
    name, date_time, org_id, uuid
FROM
    ttt2 
    JOIN
    (
        SELECT 1 AS group_number, UUID() AS `uuid`
        UNION
        SELECT 2 AS group_number, UUID() AS `uuid`
        UNION
        SELECT 3 AS group_number, UUID() AS `uuid`
        UNION
        SELECT 4 AS group_number, UUID() AS `uuid`
        -- and as many as you might need
    ) u ON u.group_number = ttt2.group_number 
ORDER BY
    name, date_time ;

你终于得到了你想要的东西

name | date_time           | org_id | uuid                                
:--- | :------------------ | -----: | :-----------------------------------
KK   | 2017-01-01 11:37:33 |      1 | 636bd83f-5d3f-11e7-8f8c-00163ebcde7e
SK   | 2017-04-19 01:36:34 |      2 | 636bd8b9-5d3f-11e7-8f8c-00163ebcde7e
SK   | 2017-04-19 01:36:53 |      2 | 636bd8b9-5d3f-11e7-8f8c-00163ebcde7e
SK   | 2017-04-19 01:37:23 |      2 | 636bd8b9-5d3f-11e7-8f8c-00163ebcde7e
TK   | 2017-02-11 01:37:20 |      5 | 636bd8c8-5d3f-11e7-8f8c-00163ebcde7e
TK   | 2017-02-11 01:37:31 |      5 | 636bd8c8-5d3f-11e7-8f8c-00163ebcde7e

通过将ttt2ttt替换为最后一个SQL上的定义,您可以在一个查询中得到您想要的内容...尽管一个&#34;怪物一个&#34;。

注意:此查询可能非常低效;并且,如果您正在编程,您可能只需循环查看已排序的数据并决定何时需要生成新的UUID,就可能更好。

您可以查看 dbfiddle here

上的所有内容

答案 1 :(得分:0)

感谢您的帮助..
我也想出了这个问题的一个大致解决方案:
这是我的疑问:

update table as u, 
        (SELECT UUID() as UUID, name, org_id,date_time 
        FROM table 
        group by name, org_id, DATE_FORMAT(date_time, "%Y-%m-%e %H-%i")) as b
set u.UUID = b.UUID
where (u.name = b.name OR (u.name is null and u.name is null)) 
    and (u.org_id = b.org_id OR ( u.org_id is null and b.org_id is null)) 
    and DATE_FORMAT(u.date_time, "%Y-%m-%e %H-%i") = DATE_FORMAT(b.date_time, "%Y-%m-%e %H-%i");
相关问题