在没有部分索引的 SQLite table 中查找 "best partial match"

Finding a "best partial match" in a SQLite table without a partial index

在我使用 SQLite 存储用户数据的 Android 应用程序中,我有一个名为 valency 的 table,如下所示。

CREATE TABLE IF NOT EXISTS valency(urid INTEGER PRIMARY KEY AUTOINCREMENT,typ INTEGER,entity INTEGER,v0 INTEGER,v1 INTEGER,v2 INTEGER,v3 INTEGER,v4 INTEGER,v5 INTEGER,lato INTEGER,data INTEGER DEFAULT 0);

CREATE INDEX IF NOT EXISTS vTypEnt ON valency(typ,entity);

我需要为 typentity 中的 table 列 v0.. v5 中的行找到 "best" 匹配项列。匹配的列数越多,我想附加到匹配的data列的权重就越大。

这就是我的流程

第 1 步 - 将相关行读入 TEMP table

CREATE TEMP TABLE H1 AS SELECT * FROM valency WHERE (typ = T) AND (entity = E);

v0..v5 值设置为 1 或 0,具体取决于它们是否匹配

UPDATE H1 SET 
v0 = CASE WHEN (v0 = V0) THEN 1 ELSE 0 END,
v1 = CASE WHEN (v1 = V1) THEN 1 ELSE 0 END,
v2 = CASE WHEN (v2 = V2) THEN 1 ELSE 0 END,
v3 = CASE WHEN (v3 = V3) THEN 1 ELSE 0 END,
v4 = CASE WHEN (v4 = V4) THEN 1 ELSE 0 END,
v5 = CASE WHEN (v5 = V5) THEN 1 ELSE 0 END;

这通常会导致 H1 中的一行或多行,其中零个或多个 v* 值设置为 0,而其他值设置为 1。我真正关心的是 "best" 匹配 - 即识别具有最多非零 v* 值的行。

步骤 3

SELECT urid,lato,data,v0 + v1 + v2 + v3 + v4 + v5 as 'vSum' FROM H1 ORDER BY vSum DESC LIMIT 1;

隔离具有 "best" 匹配项的行。在使用和操作此结果行中最匹配的 data 之前,我使用 vSum 的大小为数据分配权重。

这非常有效。但是,我不是 SQL 专家,所以我不禁想知道是否可能没有 better/simpler/faster 方法来完成同样的事情。必须使用它的上下文不需要速度,所以我不热衷于使用更多存储和更多索引的权衡。如果有人能对我的方法发表评论并提出改进建议,我将不胜感激。

您可以通过一次计算分数将select转换为一个SELECT语句。这消除了临时 table 和代码与数据库引擎之间的一些往返的需要:

select
       *
     ,  CASE WHEN (v0 = V0) THEN 1 ELSE 0 END
       +CASE WHEN (v1 = V1) THEN 1 ELSE 0 END
       +CASE WHEN (v2 = V1) THEN 1 ELSE 0 END
       +CASE WHEN (v3 = V3) THEN 1 ELSE 0 END
       +CASE WHEN (v4 = V4) THEN 1 ELSE 0 END
       +CASE WHEN (v5 = V5) THEN 1 ELSE 0 END
       + ... as vSum
  FROM valency
 WHERE (typ = T)
   AND (entity = E)
 order by vSum desc
 limit 1

您可能希望向 order by 子句添加更多条件,以确保您的顺序在运行之间保持一致。