SQLITE-使用按组自动递增的ID更新表

ubof19bj  于 2022-11-15  发布在  SQLite
关注(0)|答案(2)|浏览(163)

我有一个表格,格式如下:

CREATE TABLE my_data 
(
    category TEXT,
    projectName TEXT,
    fileName TEXT,
    fileLine TEXT,
    fdate DATETIME,
    -- other columns...
    groupid NUMBER
);

目前,groupid在所有行中都为空。
我只需要按一些列分组,并为每个组添加一个自动递增的ID。这些列是projectNamefileNamefileLine
这意味着,组中的所有行(即这三列上具有相同值的行)都应该使用相同的ID进行更新。查询应该分配自动递增的ID(这意味着现在没有值)。
我怎样才能做到这一点呢?
我在这里看到了类似的Auto-increment with Group BY,但它不起作用,因为我的数据库是SQLite,显然一些保留字在那里不起作用。
我考虑执行一个嵌套查询,比如UPDATE-SET-FROM,其中在From上有一个嵌套的group by,但我不知道如何处理每个组自动递增的ID分配。

flvlnr44

flvlnr441#

您可以按如下方式使用DENSE_RANK函数:

With CTE As
(
Select category, projectName, fileName, fileLine, fdate, groupid,
       DENSE_RANK() Over (Order By projectName, fileName, fileLine) As grp
From my_data
)
Update my_data Set groupid= CTE.grp
From CTE
Where CTE.projectName = my_data.projectName And
      CTE.fileName= my_data.fileName And
      CTE.fileLine = my_data.fileLine

查看db<>fiddle的演示。
我认为您不需要存储此值,因为您只需使用SELECT语句即可获得它:

Select category, projectName, fileName, fileLine, fdate, 
       DENSE_RANK() Over (Order By projectName, fileName, fileLine) As groupid
From my_data
pn9klfpd

pn9klfpd2#

不要这样做。

这样的表会违反数据库规范化,因为您的实际组(项目名称+文件名+文件行)可能与组ID不同步。请改为创建组表:

CREATE TABLE my_group 
(
  groupid      INTEGER PRIMARY KEY,
  projectName  TEXT,
  fileName     TEXT,
  fileLine     TEXT,
  /* other columns ? */
  UNIQUE(projectName, fileName, fileLine)
);

然后填写原始表格中的以下表格:

INSERT INTO my_group (projectName, fileName, fileLine)
  SELECT DISTINCT projectName, fileName, fileLine
  FROM my_data;

如果需要复制更多列,则有两个选项:

**选项1:**继续使用DISTINCT。如果由于UNIQUE约束,这些列值对于组来说不是唯一的,那么这将失败,并因此将您指向原始表中的数据不一致。

INSERT INTO my_group (projectName, fileName, fileLine, other_column)
  SELECT DISTINCT projectName, fileName, fileLine, other_column
  FROM my_data;

**选项#2:**告诉DBMS选择哪些值(通常是一个组的最小值、最大值或总和):

INSERT INTO my_group (projectName, fileName, fileLine, other_column)
  SELECT projectName, fileName, fileLine, MIN(other_column)
  FROM my_data
  GROUP BY projectName, fileName, fileLine;

现在您已经做到了这一点,您的表已经相关,并且您已经为每个组分配了一个组ID。如果您希望保留这些按业务键相关的表(项目名称+文件名+文件行),请在其上创建外键:

ALTER TABLE my_data
ADD CONSTRAINT fk_group
  FOREIGN KEY (projectName, fileName, fileLine) 
  REFERENCES my_group (projectName, fileName, fileLine);

你就完了。
如果您不想这样做,而是通过组ID关联表,请将其添加到您的表中:

ALTER TABLE my_data ADD COLUMN groupid INTEGER;

然后填上:

UPDATE my_data
SET groupid =
(
  SELECT groupid
  FROM my_group
  WHERE my_group.projectName = my_data.projectName
    AND my_group.fileName = my_data.fileName
    AND my_group.fileLine = my_data.fileLine
);

然后删除多余的列:

ALTER TABLE my_data DROP COLUMN projectName INTEGER;
ALTER TABLE my_data DROP COLUMN fileName INTEGER;
ALTER TABLE my_data DROP COLUMN fileLine INTEGER;

然后添加外键:

ALTER TABLE my_data
ADD CONSTRAINT fk_group
  FOREIGN KEY (groupid) 
  REFERENCES my_group (groupid);

相关问题