如何在日期和时间作为整数单独存储的情况下执行 SQL BETWEEN

发布于 2024-08-11 06:17:20 字数 831 浏览 5 评论 0原文

在我工作的公司,日期和时间值始终单独存储在整数字段中,因此例如今天早上 8:30 将存储如下:

  • 日期 20091116 和
  • 时间 83000(没有前导零,因为它是整数字段)

而当我输入这个时间时,时间将像这样存储:

  • 日期 20091116
  • 时间 133740

不幸的是,如果我想将 BETWEEN 添加到查询的 WHERE 子句中,它会带来轻微的复杂性。

目前我工作的系统正在使用类似这样的查询:

declare @minDate int, @minTime int, @maxDate int, @maxTime int
select @minDate = 20091102
select @minTime = 64841
select @maxDate = 20091105
select @maxTime = 102227

SELECT *
FROM transactions
WHERE
    (
        (
            txnDate = @minDate AND 
            txnTime >= @minTime 
        ) OR 
        txnDate > @minDate
    ) AND
    (
        (
            txnDate = @maxDate AND
            txnTime <= @maxTime
        ) OR
        txnDate < @maxDate
    )

请记住我无法更改数据库的设计...
有更好的方法吗?

At the company I work for date and time values have always been stored separately in integer fields, so for example 8:30 this morning would be stored like this:

  • date of 20091116 and
  • time of 83000 (no leading zeros as it is an integer field)

Whereas the time as I type this the time would be stored like this

  • date 20091116
  • time 133740

Unfortunately if i would like add a BETWEEN to the WHERE clause of a query it introduces a slight complication.

Currently the system I work on is using a query something like this:

declare @minDate int, @minTime int, @maxDate int, @maxTime int
select @minDate = 20091102
select @minTime = 64841
select @maxDate = 20091105
select @maxTime = 102227

SELECT *
FROM transactions
WHERE
    (
        (
            txnDate = @minDate AND 
            txnTime >= @minTime 
        ) OR 
        txnDate > @minDate
    ) AND
    (
        (
            txnDate = @maxDate AND
            txnTime <= @maxTime
        ) OR
        txnDate < @maxDate
    )

Bearing in mind that I can't change the design of the database...
Is there a better way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

流年里的时光 2024-08-18 06:17:20

如果将它们加在一起,例如:

 cast(20091116 as bigint) * 1000000 + 183000

您可以做更简单的数学。例如:

select @minDate = 20091102064841
select @maxDate = 20091105102227

select *
from (
    select cast(txnDate as bigint) * 1000000 + 
        txnTime as composite_date,
        *
    from YourTable
) sub
where composite_date between @minDate and @maxDate

另一种方法是将这两个字段转换为真正的日期时间。您可以使用计算列来执行此操作:

alter table YourTable add txnDateTime as cast(
    cast(txnDate as varchar) + ' ' + 
    cast(txnTime / 10000 as varchar) + ':' +
    cast(txnTime / 100 % 100 as varchar) + ':' +
    cast(txnTime % 100 as varchar)
 as datetime)

如果性能是一个问题,您可以使用 PERSISTED< /a> 关键字将计算的列存储在磁盘上。

If you add them together, like:

 cast(20091116 as bigint) * 1000000 + 183000

You can do simpler math. For example:

select @minDate = 20091102064841
select @maxDate = 20091105102227

select *
from (
    select cast(txnDate as bigint) * 1000000 + 
        txnTime as composite_date,
        *
    from YourTable
) sub
where composite_date between @minDate and @maxDate

Another way is to convert the two fields into a real datetime. You could do this with a computed column:

alter table YourTable add txnDateTime as cast(
    cast(txnDate as varchar) + ' ' + 
    cast(txnTime / 10000 as varchar) + ':' +
    cast(txnTime / 100 % 100 as varchar) + ':' +
    cast(txnTime % 100 as varchar)
 as datetime)

If performance is an issue, you can use PERSISTED keyword to store the calculated columns on disk.

倾城月光淡如水﹏ 2024-08-18 06:17:20

如果您担心性能(因此在 txnDate 和 txnTime 上有索引),您应该使用这个:

SELECT * FROM transactions
WHERE (txnDate > @minDate AND txnDate < @maxDate)
   OR (txnDate = @minDate AND txnTime >= @minTime)
   OR (txnDate = @maxDate AND txnTime <= @maxTime)

否则,Andomar 的 bigint 技巧很好且清晰。

If you are concerned about performance (and thus have indices on txnDate and txnTime), you should use this:

SELECT * FROM transactions
WHERE (txnDate > @minDate AND txnDate < @maxDate)
   OR (txnDate = @minDate AND txnTime >= @minTime)
   OR (txnDate = @maxDate AND txnTime <= @maxTime)

Otherwise, Andomar's trick with bigint is fine and clear.

伪装你 2024-08-18 06:17:20

重新定义@minDate和@maxDate

declare @minDate bigint, @maxDate bigint
select @minDate = 20091102064841
select @maxDate = 20091105102227

那么也许查询可以简化为

SELECT *
FROM transactions
WHERE ((CAST(txnDate AS bigint) * 1000000) + txnTime) BETWEEN @minDate AND @maxDate

Redefine @minDate and @maxDate

declare @minDate bigint, @maxDate bigint
select @minDate = 20091102064841
select @maxDate = 20091105102227

Then perhaps the query can be simplified to

SELECT *
FROM transactions
WHERE ((CAST(txnDate AS bigint) * 1000000) + txnTime) BETWEEN @minDate AND @maxDate
不忘初心 2024-08-18 06:17:20

您应该计算日期和时间组件并创建一个包含 DATETIME 的值。您应该对@variables 执行相同的操作。然后你再做比较。

这样做可以给您带来多种优势,例如数据验证、日期时间函数、准确性等。

declare @minDate int, @minTime int, @maxDate int, @maxTime int
select @minDate = 20091102
select @minTime = 64841
select @maxDate = 20091105
select @maxTime = 102227

DECLARE @MinDateTime DateTime

select @MinDateTime =
    cast (convert (varchar, @minDate / 10000) + '/' +
    convert (varchar, (@minDate % (@minDate / 10000))/100) + '/' +
    convert (varchar, (@minDate % (@minDate / 1000000))) + ' ' +
    convert (varchar, @minTime / 10000) + ':' +
    convert (varchar, (@minTime % 10000)/100) + ':' +
    convert (varchar, (@minTime  % (@minTime / 100))) as datetime)

定义计算后,您可以创建一个位于此表顶部的视图,并在任何进一步的计算中使用该视图,以便您可以不必每次都重新输入计算。

You should calculate the Date and Time components and make a single value that has DATETIME in it. You should do the same for the @variables. Then you do the comparison.

Doing this gives you several advantages such as data validation, datetime functions, accuracy, etc.

declare @minDate int, @minTime int, @maxDate int, @maxTime int
select @minDate = 20091102
select @minTime = 64841
select @maxDate = 20091105
select @maxTime = 102227

DECLARE @MinDateTime DateTime

select @MinDateTime =
    cast (convert (varchar, @minDate / 10000) + '/' +
    convert (varchar, (@minDate % (@minDate / 10000))/100) + '/' +
    convert (varchar, (@minDate % (@minDate / 1000000))) + ' ' +
    convert (varchar, @minTime / 10000) + ':' +
    convert (varchar, (@minTime % 10000)/100) + ':' +
    convert (varchar, (@minTime  % (@minTime / 100))) as datetime)

Once you have your calculation defined, you can then create a view that sits on top of this table and use the view in any further calculations so that you do not have to retype the calculation every time.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文