【问题标题】:Sqlite : Sql to finding the most complete prefixSqlite : Sql 查找最完整的前缀
【发布时间】:2009-08-07 01:12:10
【问题描述】:

我有一个包含可变长度数字前缀记录的 sqlite 表。我希望能够以最有效的方式找到针对另一个可变长度数字的最完整前缀:

例如。该表包含一个名为 prefix 的列,其中包含以下数字:

1. 1234
2. 12345
3. 123456

找到第二条记录作为与 12345999 的最完整匹配的有效 sqlite 查询是什么。

谢谢。

【问题讨论】:

    标签: sql sqlite


    【解决方案1】:

    这里有个巧妙的技巧是反转 LIKE 子句——而不是说

    WHERE prefix LIKE '...something...'
    

    就像您经常做的那样,通过在末尾附加一个 % 并将其作为固定字符串与您的输入进行比较,将 前缀 转换为模式。按前缀长度降序排列,选择前 1 个结果。

    我以前从未使用过 Sqlite,但刚刚下载了它,它工作正常:

    sqlite> CREATE TABLE whatever(prefix VARCHAR(100));
    sqlite> INSERT INTO WHATEVER(prefix) VALUES ('1234');
    sqlite> INSERT INTO WHATEVER(prefix) VALUES ('12345');
    sqlite> INSERT INTO WHATEVER(prefix) VALUES ('123456');
    sqlite> SELECT * FROM whatever WHERE '12345999' LIKE (prefix || '%') 
            ORDER BY length(prefix) DESC LIMIT 1;
    

    输出:

    12345
    

    【讨论】:

    • 跟进:我一直在iPhone应用程序中使用这种方法,发现它很慢。我现在正在寻找一些优化,找到后会在这里发布。 “ GLOB 和 LIKE 运算符在 SQLite 中很昂贵,因为它们不能使用索引。原因之一是它们是由可以被覆盖的用户函数实现的,因此解析器无法知道它们在其中的行为方式情况。这会强制对要匹配的列的表进行全面扫描,即使该列有索引。"
    【解决方案2】:

    我个人使用 next 方法,它会使用索引:

    语句'('1','12','123','1234','12345','123459','1234599','12345999','123459999')' 应该由客户端生成

    SELECT * FROM whatever WHERE prefix in
    ('1','12','123','1234','12345','123459','1234599','12345999','123459999')
    ORDER BY length(prefix) DESC LIMIT 1;
    

    【讨论】:

    • 同样按前缀排序(不使用长度)应该得到相同的结果。
    【解决方案3】:
    select foo, 1 quality from bar where foo like "123*"
    union
    select foo, 2 quality from bar where foo like "1234*"
    order by quality desc limit 1
    

    我还没有测试过,但是这个想法可以在其他 SQL 方言中使用

    【讨论】:

      【解决方案4】:

      几个假设。

      1. 您正在加入某个其他表,因此您想知道要加入的表中每条记录的最大可变长度前缀。
      2. 您的前缀表实际上不仅仅是您在示例中提供的三个...否则您可以对逻辑进行硬编码并继续前进。
      prefix_table.prefix
      1234
      12345
      123456
      etc.
      
      foo.field
      12345999
      123999
      
        select
         a.field,
         b.prefix,
         max(len(b.prefix)) as length
        from
         foo a inner join prefix_table b on b.prefix = left(a.field, len(b.prefix))
        group by
         a.field,
         b.prefix
      

      请注意,这是未经测试的,但在逻辑上应该是有道理的。

      【讨论】:

        【解决方案5】:

        如果不求助于专门的索引,最好的策略可能是寻找答案。

        对每个可能的前缀发出 LIKE 查询,从最长的开始。一旦返回行就停止。

        这当然不是实现您不想要的最漂亮的方式,但与其他建议相反,查询规划器将考虑索引。与往常一样,这取决于您的实际数据。特别是,您的表中有多少行,以及平均搜索时间。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-31
          • 2013-10-31
          • 2012-07-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-11
          • 1970-01-01
          相关资源
          最近更新 更多