【问题标题】:Sqlite: Iterating through substrings of a string fieldSqlite:遍历字符串字段的子字符串
【发布时间】:2012-07-29 01:52:24
【问题描述】:

我有一个包含一串数字的字段

 "2002 2005 2001 2006 2008 2344"

我们最好假设空格是分割,否则,它们是 4 个字符长。

我可以选择一个子字符串:

SELECT substr(years,1,4)  FROM TABLE 

但不知道如何检查每一个。我正在尝试查找包含最接近 0 的数字的行。

我可以ORDER BYLIMIT 1

【问题讨论】:

  • 嗯,如果所讨论的字段足够短以至于不需要在 DB 层中进行检索和数学运算(即不会导致速度变慢),我就将其拉出来带有光标的数据库并在其上使用StringUtils#split(String)。从那里我将使用返回的String[],将其放入 Collections#sort() 方法并检索最小值。
  • @OceanLife 不幸的是,行太多了,并且需要 3 秒以上的时间才能收回需要检查的所有行(忽略计算然后对其进行)。作为获取一行的 sql 语句会快得多(即时)。 - 目前在java代码中运行。
  • 无赖。听起来像是来自快速谷歌的问题。这个问题有一些想法,但它们看起来都很丑。用行值填充临时表的列并进行排序的想法可能会奏效。不过,不确定在每行之间清除它的开销。 stackoverflow.com/questions/11155886/…
  • 字符串中有多少个数字?最大数量是多少?
  • @GordonLinoff 它各不相同。可能是 1,可能是 20。每一行都会有所不同:|

标签: android sql sqlite for-loop substring


【解决方案1】:

这看起来很丑,但它在一个 SQLlite 语句中选择了您需要的所有内容。如果假设日期在当前间隔内,例如 1900..2100,您也可以进行一些优化。在这种情况下,您可以先剪切 2 个选择 B,C (B: 1 union 2) (C: 9 union 0 union 1)

 select years2,years from 
    (
    select i1||i2||i3||i4  as years2 from (select '0' as i1 
                   union all 
                   select '1' as i1
                   union all 
                   select '2' as i1
                   union all 
                   select '3' as i1
                   union all 
                   select '4' as i1 
                   union all 
                   select '5' as i1 
                   union all 
                   select '6' as i1
                   union all 
                   select '7' as i1
                   union all 
                   select '8' as i1
                   union all 
                   select '9' as i1) B, 
    (select '0' as i2 
                   union all 
                   select '1' as i2
                   union all 
                   select '2' as i2
                   union all 
                   select '3' as i2
                   union all 
                   select '4' as i2 
                   union all 
                   select '5' as i2 
                   union all 
                   select '6' as i2
                   union all 
                   select '7' as i2
                   union all 
                   select '8' as i2
                   union all 
                   select '9' as i2) C,
    (select '0' as i3 
                   union all 
                   select '1' as i3
                   union all 
                   select '2' as i3
                   union all 
                   select '3' as i3
                   union all 
                   select '4' as i3 
                   union all 
                   select '5' as i3 
                   union all 
                   select '6' as i3
                   union all 
                   select '7' as i3
                   union all 
                   select '8' as i3
                   union all 
                   select '9' as i3) D,
                  (select '0' as i4 
                   union all 
                   select '1' as i4
                   union all 
                   select '2' as i4
                   union all 
                   select '3' as i4 
                   union all 
                   select '4' as i4 
                   union all 
                   select '5' as i4 
                   union all 
                   select '6' as i4
                   union all 
                   select '7' as i4
                   union all 
                   select '8' as i4
                   union all 
                   select '9' as i4) E
    ) YearsAll

   left join YearsTable on (YearsTable.years like '%'||YearsAll.years2||'%')

    where YearsTable.years is not null

    order by years2 limit 1

【讨论】:

  • 好吧,除了左连接,我大部分都跟着。 % 不应该在yearsTable.years 附近吗?很好的努力。我可能会试一试。 +1
  • YearsTable.years 是您的长字符串 ""2002 2005 2001 2006 2008 2344"。YearsAll 包含从 0000 到 9999 的所有年份。因此,例如记录此条件如下所示:' 2002 2005 2001 2006 2008 2344 ' like ' %2002% '。所以如果 2002 在此字符串中,则为真。此外,只要条件为 '%year%',我已将第一个和最后一个空格 '' 添加到年份中
  • 固定连接条件。不需要在条件中使用额外的空格,因为所有数字都有固定的(4 个字符)长度并用空格分隔
【解决方案2】:

您可以使用公用表表达式将年份字符串中的年份拆分出来,然后得到最接近 0 的年份。

WITH split_years(year, years) AS (
    values(0, '2001 2002 2003 2004 2005 2006'||' ')
    UNION ALL SELECT
    cast(substr(years, 0, instr(years, ' ')) as int),
    substr(years, instr(years, ' ')+1)
    FROM split WHERE length(years)
) SELECT year FROM split_years WHERE year>0 ORDER BY year LIMIT 1;

输出是:

2001

【讨论】:

    猜你喜欢
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 2014-12-30
    • 1970-01-01
    相关资源
    最近更新 更多