【问题标题】:Selecting records based on start and end datetime fields根据开始和结束日期时间字段选择记录
【发布时间】:2012-10-24 13:39:26
【问题描述】:

我正在使用 delphi 2010 和 Firebird(本地)进行测试,但最终将针对 MS Sql Server 或 Oracle 运行我的应用程序。

如果我有日期时间字段(开始时间和结束时间),并且我想选择过去 30 天的所有记录,或者一系列日期,我该怎么做,考虑到上面提到的三个数据库(火鸟, sql server, oracle)

示例日期时间字段如下所示:10/15/2012 9:20:49 AM

以下是一个示例 sql 语句,我想在其中添加一个额外的 where 子句:

  SQL.Text:= 
      'SELECT J.id, MIN(p.start_Time) as startTime, MAX(p.end_Time) as endTime, ' 
      +  'SUM(p.duration) as TotalDuration ' 
      + 'FROM phases p ' 
      + 'JOIN jobs j ON j.id = p.jobs_Id ' 
      + 'WHERE j.id=:jobId ' 
      + 'GROUP BY j.id';
  1. 如何从开始时间或结束时间在过去 30 天内的阶段中选择所有记录?

  2. 如何从开始时间或结束时间在某个日期范围内的阶段中选择所有记录 (例如,我正在使用参数:beginDateRange & :endDateRange)

感谢您的帮助

【问题讨论】:

  • 它不会像整数一样工作吗? (column_date < :endDateRange) and (column_date >= :beginDateRange) ?对于“last 30”,您只需设置 beginRange 并省略 endRange 的条件
  • 对于“最后 30 个”,您也可以使用 datediff (day from current_date to cast(? as date)) - 尽管它可能是 Firebird-only 构造:firebirdsql.org/refdocs/langrefupd21-intfunc-datediff.html

标签: sql delphi delphi-2010


【解决方案1】:

如果您的列(start_time 和 end_time)被声明为相应 DB 的适当日期类型,您应该能够简单地使用 AsDateTime 函数设置参数。

Query1.ParamByName('start_time').AsDateTime := Date-30
Query1.ParamByName('end_time').AsDateTime := Date;

这应该适用于不同的数据库 - 例如,如果它们在 Firebird 中声明为时间戳,在 Oracle 中声明为日期。根据您构建查询的方式,您可以使用相同的 SQL 语句并根据结果集的要求设置 start_time 和 end_times。根据您实际要检索的内容,以下内容应根据 start_time 返回最近 30 天的记录。

例如:

SQL.Text:= 
      'SELECT J.id, MIN(p.start_Time) as startTime, MAX(p.end_Time) as endTime, ' 
      +  'SUM(p.duration) as TotalDuration ' 
      + 'FROM phases p ' 
      + 'JOIN jobs j ON j.id = p.jobs_Id ' 
      + 'WHERE j.id=:jobId '
      + '  and Trunc(p.start_time) >= :beginDateRange and Trunc(p.start_time) <= :endDateRange '
      + 'GROUP BY j.id';
ParamByName('beginDateRange').AsDateTime := Date - 30;
ParamByName('endDateRange').AsDateTime := Date;

Firebird 和 Oracle 将处理 between 语法,但不确定 SQL Server(但大概可以)。在这种情况下,您可以将 and 子句更改为:

and Trunc(p.start_time) between :beginDateRange and :endDateRange

【讨论】:

  • 你似乎遗漏了这个词:在 date1 和 date2 之间。见firebirdsql.su/doku.php?id=select
  • 我收到“来自字符串的转换错误 - 10-25-2012”,我不知道为什么,因为我的日期时间字段位于“2012 年 10 月 25 日上午 9:20:49 “ 格式。会不会是日期函数?
  • 我将其更改为以下内容: ParamByName('beginDateRange').AsString := formatDateTime('mm/dd/yyyy',Date - 30) .....我收到错误“来自字符串的转换错误 - 2012 年 10 月 25 日"
  • 这仍未解决,因为您的答案似乎不起作用。在上面的评论中查看我的错误
  • @JakeSnake 请为表格阶段发布您的 DDL。需要知道您为 start_time 和 end_time 字段分配的数据类型。它们是 DateTime 还是 VarChar 还是什么...正如我在您提出的另一个问题上看到的那样,您在最喜欢的 DB Explorer(例如 IBXpert、IBConsole 等)中看到的日期表示形式并不一定决定值是存储在数据库中。
【解决方案2】:

确保数据库是根据日期和时间排序的,然后你可以运行一个循环来找到日期大于 31 的第一个条目。然后你知道你可以从那个字段索引号向上循环...... . 使用 adotable 删除第一个循环。当它检索所有数据时,在while循环中添加sql。

虽然不可爱。BOF 做

....... 如果使用 oracle,还有很多其他方法和更好的方法。 只考虑这背后的概念和逻辑,因为 adotable 不会是

【讨论】:

  • Rudi,也许我听错了,但你不是建议对数据库中的所有记录进行排序并获取到客户端吗?如果是这样,我希望你永远不要在商业应用中做这样的事情:-)
  • @TLama 表示“过去 30 天”,这可能是完全有效的建议,假设表没有“来自未来”的行。但是对于“在 date1 和 date2 之间”这很糟糕,我同意。
  • 我知道如果检索到数据并且变得易受攻击,可以从客户端检索数据......但正如我所说,如果它已排序,那么您最多只能检索 30 天的字段而无需触及任何其他字段...排序后在循环中运行 sql,然后您只能检索相关数据。如果您对字段进行排序,使用参数,并且不将检索到的数据存储在客户端集中,它将是安全的
  • 我只是在 30 天后才看到问题的第二部分,而不是中间......对不起我的错误
猜你喜欢
  • 2021-08-05
  • 2017-01-15
  • 2020-05-07
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多