我有一个表,它有一些列,如ID,名称等。还有一个包含JSON对象的列。由于一个错误,有些行被复制了。我一直在尝试编写一个查找所有重复项的查询。
JSON示例:
{"flowId":"63","nodeId":2,"triggerLogId":"39397","modelId":"146",...}
我希望能够找到上述内容的副本,其中一切都是相同的,除了“triggerLogId”可以是两个不同的数字。
可能重复的JSON示例:
{"flowId":"63","nodeId":2,"triggerLogId":"56217","modelId":"146",...}
如果两个行上的triggerLogId相同,我想出了一些查询来执行此操作,但我似乎无法找到可用于比较两列的任何正则表达式。
据我所知,MySQL没有正则表达式反向引用,所以我不能使用它们。这在纯MySQL中甚至可能吗? flowId和modelId可以是各种数字,因此列出一些不会起作用。
搜索了大部分Stack溢出问题以及大量谷歌搜索结果,希望有人能够知道我无法找到的内容。 :P
我最终还是要使用PHP吗?
编辑(表格结构):
id ----- int(11)自动增量
type-- varchar(20)
time-- bigint(20)NULL
data-- text
答案 0 :(得分:2)
这不是一个答案。这有望帮助某人或您自己找到答案。
使用此查询,您可以将数据值“转换”为不同的列。
SELECT id,type,time,flowId,nodeId,triggerLogId,modelId FROM
(
SELECT *,
SUBSTR(data,LOCATE('flowId',data)+LENGTH('flowId')+2, LOCATE(',',data,LOCATE('flowId',data)+LENGTH('flowId')+3) - (LOCATE('flowId',data)+LENGTH('flowId')+2)) as flowId,
SUBSTR(data,LOCATE('nodeId',data)+LENGTH('nodeId')+2, LOCATE(',',data,LOCATE('nodeId',data)+LENGTH('nodeId')+3) - (LOCATE('nodeId',data)+LENGTH('nodeId')+2)) as nodeId,
SUBSTR(data,LOCATE('triggerLogId',data)+LENGTH('triggerLogId')+2, LOCATE(',',data,LOCATE('triggerLogId',data)+LENGTH('triggerLogId')+3) - (LOCATE('triggerLogId',data)+LENGTH('triggerLogId')+2)) as triggerLogId,
SUBSTR(data,LOCATE('modelId',data)+LENGTH('modelId')+2, LOCATE('}',data,LOCATE('modelId',data)+LENGTH('modelId')+3) - (LOCATE('modelId',data)+LENGTH('modelId')+2)) as modelId
FROM `my_table`
)
as foo
我会继续尝试找到问题的答案并更新我的答案。
<强>更新强>
这会解决您的问题吗?
SELECT CAST(GROUP_CONCAT(id) AS CHAR(1000)) as duplicated_rows
FROM `test`
GROUP BY CONCAT(SUBSTR(data,LOCATE('flowId',data)+LENGTH('flowId')+2, LOCATE(',',data,LOCATE('flowId',data)+LENGTH('flowId')+3) - (LOCATE('flowId',data)+LENGTH('flowId')+2)),
SUBSTR(data,LOCATE('nodeId',data)+LENGTH('nodeId')+2, LOCATE(',',data,LOCATE('nodeId',data)+LENGTH('nodeId')+3) - (LOCATE('nodeId',data)+LENGTH('nodeId')+2)),
SUBSTR(data,LOCATE('modelId',data)+LENGTH('modelId')+2, LOCATE('}',data,LOCATE('modelId',data)+LENGTH('modelId')+3) - (LOCATE('modelId',data)+LENGTH('modelId')+2)))
HAVING COUNT(*) > 1
DELETE DUPLICATES
我甚至不接近成为MySQL的专家,所以可能(最肯定)这甚至都不是最好的答案。要删除重复的行并保留最后一行(即只留下ID最高的行),我们需要两个步骤:
使用此查询获取我们要删除的ID列表:
SELECT GROUP_CONCAT(delete_rows)为delete_ids FROM(SELECT SUBSTR(GROUP_CONCAT(id),1,(LENGTH(GROUP_CONCAT(id)) - LOCATE(',',REVERSE(GROUP_CONCAT(id)))))作为delete_rows 从测试 GROUP BY CONCAT(SUBSTR(数据,LOCATE('flowId',数据)+ LENGTH('flowId')+ 2,LOCATE(',',data,LOCATE('flowId',data)+ LENGTH('flowId')+ 3) - (LOCATE('flowId',data)+ LENGTH('flowId')+ 2)),SUBSTR(data,LOCATE('nodeId',data)+ LENGTH('nodeId')+ 2,LOCATE(', ',data,LOCATE('nodeId',data)+ LENGTH('nodeId')+ 3) - (LOCATE('nodeId',data)+ LENGTH('nodeId')+ 2)),SUBSTR(data,LOCATE( 'modelId',data)+ LENGTH('modelId')+ 2,LOCATE('}',data,LOCATE('modelId',data)+ LENGTH('modelId')+ 3) - (LOCATE('modelId',数据)+ LENGTH('modelId')+ 2))) 有计数(*)&gt; 1)如foo GROUP BY'';
该查询将返回(1,5,7,8,10)
之类的ID列表。在下一个查询中复制该列表:
DELETE FROM test WHERE id IN <copy_list_here>
最终更新
我找到了一种只使用一个查询即可完成此任务的方法。
DELETE FROM test WHERE FIND_IN_SET(id,
(SELECT GROUP_CONCAT(delete_rows) as delete_ids
FROM ( SELECT SUBSTR(GROUP_CONCAT(id),1,(LENGTH(GROUP_CONCAT(id)) - LOCATE(',',REVERSE(GROUP_CONCAT(id))))) as delete_rows
FROM test
GROUP BY CONCAT(SUBSTR(data,LOCATE('flowId',data)+LENGTH('flowId')+2, LOCATE(',',data,LOCATE('flowId',data)+LENGTH('flowId')+3) - (LOCATE('flowId',data)+LENGTH('flowId')+2)), SUBSTR(data,LOCATE('nodeId',data)+LENGTH('nodeId')+2, LOCATE(',',data,LOCATE('nodeId',data)+LENGTH('nodeId')+3) - (LOCATE('nodeId',data)+LENGTH('nodeId')+2)), SUBSTR(data,LOCATE('modelId',data)+LENGTH('modelId')+2, LOCATE('}',data,LOCATE('modelId',data)+LENGTH('modelId')+3) - (LOCATE('modelId',data)+LENGTH('modelId')+2)) )
HAVING COUNT(*) > 1) as foo
GROUP BY ''
));