SQL日期间隔算法

SQL日期间隔算法,sql,delphi,date,db2,Sql,Delphi,Date,Db2,我目前正在编写一个Delphi应用程序,它使用ADO在DB2数据库上运行查询 其中一项要求是,用户应该能够使用日期定义查询,例如,显示过去60天的所有数据或显示2009年11月20日至2010年1月18日之间的所有数据。这不是一个问题,除了两个事实: 日期使用日、月和年的不同字段存储在数据库中。 数据库已在多个客户站点使用多年,无法更改,因此应用程序必须在现有数据库上运行,因此不会更改数据库以将日期存储在一个字段中,这将使任务更简单。 我需要知道的是,是否有一种高效的算法来构造从数据库中提取指定

我目前正在编写一个Delphi应用程序,它使用ADO在DB2数据库上运行查询

其中一项要求是,用户应该能够使用日期定义查询,例如,显示过去60天的所有数据或显示2009年11月20日至2010年1月18日之间的所有数据。这不是一个问题,除了两个事实:

日期使用日、月和年的不同字段存储在数据库中。 数据库已在多个客户站点使用多年,无法更改,因此应用程序必须在现有数据库上运行,因此不会更改数据库以将日期存储在一个字段中,这将使任务更简单。 我需要知道的是,是否有一种高效的算法来构造从数据库中提取指定信息所需的SQL。例如,今天是1月18日,所以要提取从11月20日到今天的所有信息,我需要一个SQL语句,如下所示:

SELECT data WHERE 
((day >= 20) AND (month = 11) AND (year = 2009)) OR 
((month = 12) AND (year = 2009)) OR 
((day <= 18) AND (month = 1) AND (year = 2010))
显然,这是一个简单且相对简单的示例,但是如果用户希望检索2008年11月而不是2009年的数据,那么查询将变得更大


这是我构造SQL语句的唯一方法,还是有更有效的方法来实现这一点?

您可以构造它以将年/月/日转换为日期数据类型,但这会阻止使用索引,因此性能可能会有问题

db2是否有可以索引的计算列,您是否能够添加这些列?或者可能是一个具有索引/持久化计算列的视图


但是,如果您在年/月/日上有索引,那么您拥有的代码可能是性能最佳的代码。

您可以将其构造为将年/月/日转换为日期数据类型,但这将阻止使用索引,因此性能可能会有问题

db2是否有可以索引的计算列,您是否能够添加这些列?或者可能是一个具有索引/持久化计算列的视图


但是,如果您有年/月/日的索引,那么您拥有的代码可能是性能最佳的代码。

在DB2中,以下内容应将单独的列转换为日期类型: 日期年|月|日

如果您有两个日期,可以使用减法来接收两个日期之间的天数,因此where子句可以包括


dateyear | | month | | day>CURRENT | DATE-60在DB2中,以下内容应将单独的列转换为日期类型: 日期年|月|日

如果您有两个日期,可以使用减法来接收两个日期之间的天数,因此where子句可以包括


dateyear | | | month | | day>CURRENT | u DATE-60在MSSQL中,我将尝试编写一个函数来返回自数据日期起的天数。在Firebird中,我会使用Delphi用户定义函数或至少一个可选择的存储过程来做同样的事情。我不知道是否可以使用这两个选项中的任何一个来扩展DB2SQL,但是如果您可以将逻辑封装成这样的东西,那么您的工作就会容易得多。我看到在页面右侧的相关文章中提到了DB2SQLUDF。我希望这会有所帮助。

在MSSQL中,我会尝试编写一个函数来返回数据日期后的天数。在Firebird中,我会使用Delphi用户定义函数或至少一个可选择的存储过程来做同样的事情。我不知道是否可以使用这两个选项中的任何一个来扩展DB2SQL,但是如果您可以将逻辑封装成这样的东西,那么您的工作就会容易得多。我看到在页面右侧的相关文章中提到了DB2SQLUDF。我希望这会有所帮助。

因为要与日期进行比较,所以应该首先将非日期值转换为日期。这使您能够将日期与日期进行比较,从那里很容易

因为您要与日期进行比较,您应该首先将非日期值转换为日期。这使您能够将日期与日期进行比较,从那里很容易

Galghamon提供的答案在代码方面是有效的,但无法利用索引

我建议您在Delphi中执行所有必要的计算,以便从概念上将您的逻辑简化为以下之一:

(DateCol > @DateVal)
(DateCol >= @DateVal)
(DateCol < @DateVal)
(DateCol <= @DateVal)
(DateCol = @DateVal)

注意:您需要精确地知道在何处使用inclusive和在何处使用exclusive不等式运算符。

Galghamon提供的答案在代码方面是有效的,但无法利用索引

我建议您在Delphi中执行所有必要的计算,以便从概念上将您的逻辑简化为以下之一:

(DateCol > @DateVal)
(DateCol >= @DateVal)
(DateCol < @DateVal)
(DateCol <= @DateVal)
(DateCol = @DateVal)

注意:您需要精确说明在何处使用inclusive和在何处使用exclusive不等式运算符。

关于您对数据库更改的评论。考虑为T添加单个列 他在约会。此列将仅由触发器写入,并且至少更新了其中一列day、month和year。这样,您就可以自由地为本专栏编制索引并使用它

您不会影响任何现有软件,并且可以方便地使用日期列。请记住,您今天编写的代码需要在6个月内被其他开发人员读取


因此,如果你仍然不能使DB改变考虑GalHAMON的解决方案,因为它很容易理解低维护成本。只有当性能影响迫使您这样做时,才使用Craig Young的解决方案。

关于您对数据库更改的评论。考虑为日期添加单个列。此列将仅由触发器写入,并且至少更新了其中一列day、month和year。这样,您就可以自由地为本专栏编制索引并使用它

您不会影响任何现有软件,并且可以方便地使用日期列。请记住,您今天编写的代码需要在6个月内被其他开发人员读取


因此,如果你仍然不能使DB改变考虑GalHAMON的解决方案,因为它很容易理解低维护成本。只有当性能影响迫使您这样做时,才使用Craig Young的解决方案。

您不能添加视图以将日期部分转换为单个日期对象,并查询出该视图?您不能添加视图以将日期部分转换为单个日期对象,并查询出该视图?与Galghamon的回答相同;但问题是你失去了索引的好处;但问题是你失去了索引的好处,这是最复杂的选择。你想写一个函数,它必须考虑每个月不同的天数,闰年与非闰年,以及闰年规则的例外情况?我同意你的观点,克雷格。我也不是建议走那条路。我不熟悉DB2SQL,所以我不知道有一个函数可以像Galghamon建议的那样简单。我担心从一天、一个月、一年构造一个日期可能会更困难,在函数或udf中放入一堆代码会使它更容易使用。这是最复杂的选择。你想写一个函数,它必须考虑每个月不同的天数,闰年与非闰年,以及闰年规则的例外情况?我同意你的观点,克雷格。我也不是建议走那条路。我不熟悉DB2SQL,所以我不知道有一个函数可以像Galghamon建议的那样简单。我担心从一天、一个月和一年构造一个日期可能会更困难,在函数或udf中放入一堆代码会使它更易于使用。数据库位于服务器上,所有服务器端软件以及数据库维护都由另一个团队执行。我的项目的任务是能够从PC机上对服务器上现有的数据库/程序结构运行查询,因此不幸的是,我甚至不能添加触发器等。我的第一个想法当然是添加一个日期列,但我的手被这一列束缚住了,因此我的问题是,数据库在服务器上,所有服务器端软件以及数据库维护都由另一个团队执行。我的项目的任务是能够从PC机上对服务器上现有的数据库/程序结构运行查询,因此不幸的是,我甚至不能添加触发器等。我的第一个想法当然是添加一个日期列,但我的手被这一列束缚住了,因此我的问题是。我该如何在查询中包括这一列?例如,假设我想要检索从日期=2009-12-31到今天的所有数据。日期如何适合查询字符串?我认为date以三个整数值作为参数year,month,day,对吗?在哪里引用与日期关联的字段?某些数据库表包含多个日期信息,因此我显然需要查询正确的字段。日期采用字符串-我使用双管道| |运算符连接现有的三个字段。您应该能够将我的声明复制并粘贴到您的where子句中,以获得最后60天。如果您想要从去年年底开始的所有内容,包括年终,则可以使用WHERE dateyear | | month | date>=date'20091231'。我假设您的一位数月份和天数是以前导零存储的,因此您可能必须格式化这些列,并用“0”填充每个列,以获得两位数。为了进行比较,您可以删除日期,因为alpha排序就可以了。我尝试使用date函数,但它不起作用。我得到了函数CONCAT的一个错误参数*N无效,因此很明显,在日期函数中指定字段,并将其连接在一起,是不起作用的,除非我完全误解了应该在哪里引用字段th
至少需要查询。别担心,我会接受你的答案。我认为您的回答值得一试,因为您的值是数字,而不是字符串,并且在DB2中串联不适用于数字,似乎我通常使用Oracle。您可以使用DIGITS函数,前提是数字的精度在年份为4,在月份和日期字段为2。数字将根据需要在数字的左边填充0,直到达到字段的精度。因此,我最初回答的完整示例是DATEDIGITSyear | | DIGITSmonth | | DIGITSday>CURRENT|U DATE-60。如果精度更高,则必须执行SUBSTRDIGITSyear,1,4来对每个字段进行精简。但是,我如何在查询中包含这一点呢?例如,假设我想要检索从日期=2009-12-31到今天的所有数据。日期如何适合查询字符串?我认为date以三个整数值作为参数year,month,day,对吗?在哪里引用与日期关联的字段?某些数据库表包含多个日期信息,因此我显然需要查询正确的字段。日期采用字符串-我使用双管道| |运算符连接现有的三个字段。您应该能够将我的声明复制并粘贴到您的where子句中,以获得最后60天。如果您想要从去年年底开始的所有内容,包括年终,则可以使用WHERE dateyear | | month | date>=date'20091231'。我假设您的一位数月份和天数是以前导零存储的,因此您可能必须格式化这些列,并用“0”填充每个列,以获得两位数。为了进行比较,您可以删除日期,因为alpha排序就可以了。我尝试使用date函数,但它不起作用。我得到了一个错误参数*N,函数CONCAT无效,因此很明显,在日期函数中指定字段并连接在一起是不可行的,除非我完全误解了应该引用要查询的字段的位置。别担心,我会接受你的答案。我认为您的回答值得一试,因为您的值是数字,而不是字符串,并且在DB2中串联不适用于数字,似乎我通常使用Oracle。您可以使用DIGITS函数,前提是数字的精度在年份为4,在月份和日期字段为2。数字将根据需要在数字的左边填充0,直到达到字段的精度。因此,我最初回答的完整示例是DATEDIGITSyear | | DIGITSmonth | | DIGITSday>CURRENT|U DATE-60。如果精度更高,则必须对每个字段执行SUBSTRDIGITSyear,1,4以将其缩小。