如果日期独立于年份在日期范围内,最好的(最快的)比较方法是什么?
表格“日期”:
some_column| since | upto |
-----------|--------------|-------------|
'foo' | '2011-05-01' | '2013-06-01'|
现在我希望此查询返回'foo'
SELECT foo FROM dates WHERE '2014-05-05' BETWEEN `since` AND `upto`
[如果需要,我可以更改“日期”表中存储日期的类型/格式,但是我不能更改输入查询的日期格式,因为该值通常来自另一个表(这是使用联接的更复杂查询的一部分) 。
使用DayOfYear功能:
SELECT foo FROM dates WHERE DayOfYear('2014-05-05')
BETWEEN DayOfYear(`since`) AND DayOfYear(`upto`)
SELECT foo FROM dates WHERE DATE_FORMAT('2014-01-15', "%m-%d")
BETWEEN DATE_FORMAT(`since`,"%m-%d") AND DATE_FORMAT(`upto`,"%m-%d")
这里是SQL FIDDLE演示
由于您已表示可以在数据中存储任意年份,因此可以继续使用DATE
类型。然后就归结为如何查询。
使用固定的任意年份存储字段。您应该使用a年来适应2月29日值的可能性。 2000年运作良好。 (0004无法使用,因为它对于MySQL的Date
类型而言太小了。)
将要查询的任何值的年份替换为同一年份。
考虑范围跨越一年的末尾,直到下一年。要完全回答这个问题,您将需要一个如下查询:
SET @dt = cast(CONCAT('2000',RIGHT(thesourcedatevalue,6)) as DATE);
SELECT some_column FROM dates
WHERE (since <= upto AND since <= @dt AND upto >= @dt) OR
(since > upto AND (since <= @dt OR upto >= @dt))
为了提高性能,您应该确保有一个包含since
和upto
字段的索引。
经过简短的google-look和stackoverlook之后,我遇到了以下2个问题:
since
和upto
)可以属于不同的年份,这使DayOfYear()成为问题。这是我想出的SQL查询。假设我们要检查日期'2014-05-05':
SELECT foo FROM `dates` WHERE
(
/* -------- since and upto are from same year -------- */
YEAR(`since`) = YEAR(`date_fin`)
AND (
(
MONTH(`since`) < "05"
OR
(
MONTH(`since`) = "05"
AND
DAY(`since`) <= "05"
)
) AND (
MONTH(`date_fin`) < "05"
OR
(
MONTH(`date_fin`) = "05"
AND
DAY(`date_fin`) >= "05"
)
)
)
)OR(
/* -------- since and upto are from different year -------- */
YEAR(`since`) <> YEAR(`date_fin`) AND (
(
MONTH(`since`) < "05"
OR
(
MONTH(`since`) = "05"
AND
DAY(`since`) <= "05"
)
) OR (
MONTH(`date_fin`) > "05"
OR
(
MONTH(`date_fin`) = "05"
AND
DAY(`date_fin`) >= "05"
)
)
)
)