2017-06-29 47 views
1

这是我在MySQL现有表
如何遍历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 

我想更新表,并插入一个独特的UUID,而不是基于零的名称是否相同,时间戳为1分钟,每次其他与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 

请让我知道我怎么写SQL脚本来做到这一点使用MySQL的工作台..

+0

贵表包含一个唯一的ID列标识行? – Barmar

+0

UUID从哪里来? – Barmar

+0

是的..我有一个自动增量ID列 – Sharvil

回答

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 

如果要更新,做一个,和更新加入您的原始表。


这由几个步骤进行。首先,你需要订购你的数据,并确定此时你需要“改变组”(我把那个叫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 

现在,您可以通过连接到的表改变group_number到UUID (1,UID1),(2,UID2)等的元组:

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 

通过用最后一个SQL的定义代替ttt2ttt,你可以在一个查询中得到你想要的东西......虽然是“怪物一个”。

注意:这个查询可能会非常低效;而且,如果您正在进行编程,您可能只需循环访问已排序的数据并确定何时需要生成新的UUID。

您可以检查一切dbfiddle here

+0

谢谢..帮了很多.. – Sharvil

+0

不客气Sharvil。如果你认为这个问题已经被回答了,那么把它标记为*接受的*或多或少是习惯的,这样人们就可以专注于已经没有回答的*的广泛列表。 – joanolo

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"); 
相关问题