Mysql按条件更新相同的表列,按列更新组

Mysql按条件更新相同的表列,按列更新组,mysql,sql,stored-functions,Mysql,Sql,Stored Functions,这是Mysql表,我想如下设置版本列。版本列有数百万条记录需要更新 File_id |file_name | type | flag | original_file_id | version 1 |abc.jpg | FILE | RENAMED | 1 | 1 3 |folder1 | FOLDER | RENAMED | 3 | null 5 |fol

这是Mysql表,我想如下设置版本列。版本列有数百万条记录需要更新

File_id |file_name |  type  | flag     | original_file_id  |  version

   1    |abc.jpg   | FILE   | RENAMED  |      1            |   1 
   3    |folder1   | FOLDER | RENAMED  |      3            |  null
   5    |folder1   | FOLDER | null     |      3            |  null
   7    |abc1.jpg  | FILE   | null     |      1            |   2 
   9    |abc1.jpg  | FILE   | DELETED  |      1            |   2 
   11   |abc.jpg   | FILE   | MOVED    |      1            |   3 
   13   |abc.jpg   | FILE   | null     |      1            |   4 
   15   |xyz.jpg   | FILE   | null     |      6            |   1 
   17   |xyz.jpg   | FILE   | DELETED  |      6            |   1 
   19   |xyz.jpg   | FILE   | null     |      6            |   2 

我想将版本设置为如上所述。对于第一个文件,其中文件id=原始文件id,则版本=1。如果删除标志,则将以前的版本设置为版本2。对于其他重命名、移动的增量版本。但它应仅更新文件,而不更新文件夹。

您可以使用此查询:

UPDATE FILES
SET version = CASE
WHEN original_file_id = File_id THEN File_id
WHEN flag = 'DELETED' THEN (SELECT F1.version-F2.version FROM FILES F1, FILES t2 WHERE F1.File_id = F2.File_id -1)
WHEN flag = 'RENAMED' THEN ((SELECT F1.version-F2.version FROM FILES F1, FILES t2 WHERE F1.File_id = F2.File_id -1)+1)
WHEN flag = 'MOVED' THEN ((SELECT F1.version-F2.version FROM FILES F1, FILES t2 WHERE F1.File_id = F2.File_id -1)+1);

您可以使用以下查询:

update files
join 
( select f1.file_id, 
    count(f2.file_id) + count(distinct forg.file_id) as version
  from files f1
  left outer join files forg
  on f1.original_file_id = forg.file_id
    and f1.original_file_id = forg.original_file_id
    and forg.flag = 'DELETED'
  left outer join files f2
  on f1.original_file_id = f2.original_file_id
    and f1.file_id >= f2.file_id 
    and coalesce(f2.flag,'') <> 'DELETED'
    and coalesce(f2.type,'') <> 'FOLDER'
  where coalesce(f1.type,'') <> 'FOLDER'
  group by f1.file_id
) fileversions
on fileversions.file_id = files.file_id
set files.version = fileversions.version
where coalesce(files.type, '') <> 'FOLDER';
它将增加每个原始\u文件\u id-group中的版本,除非它有一个标志='Deleted'。类型为“Folder”的所有行都将被忽略且不会更新

第一个file_id=original_file_id的文件将获得版本1,即使它的标志为“deleted”,在这种情况下,下一个未删除的文件将获得版本2

查询不会检查您的数据是否损坏,例如,是否存在文件id=原始文件id的文件,或者是否存在文件id为文件id<原始文件id的文件


如果要在合理的时间内完成,您需要索引原始文件id或原始文件id、文件id。

表中的主键列是什么?@jimmacoulay抱歉,我已更新了我的问题文件id为primarykey@GordonLinoff不修订版取决于标志和原始文件id。版本与原始文件id不一致。现在检查。您是否了解了?我了解了,但我通过更改表列中添加的类型列再次更新了我的问题。请立即检查此项。我只需要更新文件,而不需要更新文件夹。因此,对于文件id,它不总是增量1。在每个where条件之后提供**和F1。type='FILE'**。你能做到吗?或者您需要再次执行整个查询?这很好,我可以添加条件,其中type=FILE,但F1.FILE\u id=F2.FILE\u id-1有效吗?因为您无法确保下一个文件\u id。假设abc.jpg file\u id为3,那么下一个文件\u id可以是60。因此,对于这里,F1.file\u id=F2.file\u id-1,我可以做什么?您的查询依赖于每个组的连续文件\u id,没有间隙,中间没有其他文件组。我认为这不是一个有效的假设。感谢您的帮助。但我有一些疑问。1如果组的第一个文件具有该标志,则其版本设置为0。这不应是预期的,因为第一个文件总是获取版本1,而不是其他任何内容。2如果某个地方的原始文件记录已损坏,那么该如何处理?与originalfileid 50一样,该组有3个文件,文件id为51、52、53,原始文件id为50,但originalfileid和文件id为50的文件已损坏。1如果删除第一个条目,会发生什么情况?你说一个被删除的文件应该得到之前的版本,它不存在2我不明白你的意思,你能给出一个例子和你想要的结果吗?但一般来说:如果您的数据不干净,您就不能期望得到干净的结果。你是说像原始文件那样的东西吗?即使文件\u id=6不存在,我的查询也会为您提供问题中关于文件\u id=15的第1版的确切输出。忘记损坏数据的第2个条件。但必须存在第1个条件,即文件id=originalfileid的文件,其版本始终为1。例如,在我的例子中,带有文件ID 1和15的表文件是第一个文件,原始文件ID总是与FLAG无关,因为无论在什么之后都需要考虑FLAG。所有的东西都是完美的,除非这个条件版本必须从1开始。它不应该是零。所以假设在你的示例数据中,FielyID的1, 7和9将删除该标志,文件ID 1、7、9和11的版本是:1、1、1、2?对的