为了获得最佳性能,需要有对datetime
字符串列一个合适的索引。我会建议(不一定建议)一种避免一些其他查询模式潜在性能问题的方法。
我建议的方法是利用多个查询,每个查询返回一个包含新的年份值的单行。 (我假定将有只有几个不同的年份值,很多行对于给定的一年。)
让我们假设我现有的几年列表包含2011年,2013年和2014年
以下描述了我将运行的查询的顺序,利用现有的值作为我运行的查询中的谓词。基本的想法是,我只需要在给定的一年中找到一行......不需要读取全部的行。
我需要现有的年份列表才能顺利。我会从最低值开始,然后运行一个查询,获得该年之前的最早日期。我希望能够最有效地使用索引的查询以及Sqllite中的优化。
我在现有列表中的最早年份值是'2011'。我推说进入查询......我的第一个镜头会是这样的:
select dt from t where dt < '2011-01-01'
order by dt limit 1
如果我没有得到行了,我知道,2011年是最早的一年。
如果我确实得到了一排,我知道这是一个“新”年。我会将前四个字符作为年份,并将其添加到我的列表中。我会比较2011年的这一年的价值,如果差距超过一个,我会检查下一个最低年份。
例如,如果该查询返回与“2008”的开始日期,下一个查询我运行与2008年后的最低日期时间与上年行检查,但在2011年之前
select dt from t where dt < '2011-01-01'
and dt >= datetime('2008-01-01','+1 years')
order by dt limit 1
如果我没有再回来,我知道在2011年之前没有更多的“新”年值。我的下一个查询将使用2011年作为下限,并且我现有列表中的下一年值将作为上限,并且再次重复相同的查询。
如果我得到行回来了,日期时间,随着2009年开始我要补充2009年进入我的列表,我的下一个查询酷似上面的一个,但与2009年到位2008 ...
select dt from t where dt < '2011-01-01'
and dt >= datetime('2009-01-01','+1 years')
order by dt limit 1
同样地,如果我没有得到一排,那时我才知道有没有更多的新的一年在2011年之前
所以,现在2011年是我的下界,并于次年在我现有的列表上限。所以,同样的查询再次,只有改变了一年的文字...
select dt from t where dt < '2013-01-01'
and dt >= datetime('2011-01-01','+1 years')
order by dt limit 1
如果我得到一排,这是一个新的一年里要添加到我的名单。这是我下一个查询的新下界。如果没有行,那么最后一个查询的上限是新的下限。
为了优化模式,我会跳过运行一个我知道不会返回一行的查询。当我已经有2013年和2014年在我的名单,我的查询将是这种模式的......
select dt from t where dt < '2014-01-01'
and dt >= datetime('2013-01-01','+1 years')
order by dt limit 1
,但我们知道,有同时满足这两个条件的任何行。一行不能有小于2014并且大于或等于2014的dt值,这是不可能的条件,所以我们可以跳过执行它。
当我到达列表中的最后一个值时,我将删除上限条件......我不在乎下一个查询是否返回2015年,2017年或2032年...无论是最近一年我在我的名单中。
select dt from t where
dt >= datetime('2014-01-01','+1 years')
order by dt limit 1
如果我收回一行,将该年添加到列表中,并将其用作我的下一个下限。并重复,直到我没有排队回来。
这确实运行了几个查询,但它们应该非常有效。在Hugh Jass表格中,这些可能是查找新年值最有效的查询。
如果这种模式发生故障,那么当我们需要运行大量查询时,当我们需要检查很多“空白”时。
这种模式最糟糕的情况将是以数字结尾的数百个现有年份值。每年的价值都有差距,我们必须检查它们之间的差距。
但是这种模式的最好情况是连续年值的长列表。如果没有找到新的年份值,我们最多可以运行两个查询。一个检查较早的一年(未找到),另一个检查较晚的一年(未找到)。
同样,这种方法的性能完全取决于其对dt
一个适当的索引和查询计划,有效地使用该索引的。
我们不一定需要使用'datetime'函数向日期文本添加一年,我们可以轻松地在客户端上处理该日期,并将年份值加1。 (我使用datetime函数来说明我们使用的是我们检索的年份值,或者是在我们的列表中。这还假定“日期时间字符串”列以一致的格式存储,并且前导日期部分位于格式为“'yyyy-mm-dd'” – spencer7593
如果我们从一个现有的年份值列表开始,它是* empty *,我们的第一个查询在dt列上将没有谓词(条件),只是最早得到 – spencer7593
谢谢对于这个有趣的算法的仔细解释!顺便说一句,你的假设是正确的:虽然数据库可能用于说30年,但在大多数时间,我将有一个连续的同一年的条目列表(这将有相同的格式,'yyyy/MM/dd'。 – Momergil