Sql 将日期拆分为多个字段时按日期范围筛选
我正在使用一个数据库,该数据库将日期作为整数(模拟字段名)存储在多个字段中:Sql 将日期拆分为多个字段时按日期范围筛选,sql,db2,Sql,Db2,我正在使用一个数据库,该数据库将日期作为整数(模拟字段名)存储在多个字段中: 世纪:CC01:20 年份:YR01:13 月份:MO01:7 日期:DY01:22 我可以这样表述一个日期:date((CC01*100+YR01)| |'-'| | MO01 | |'-'| | DY01) 问题是当我需要过滤一系列日期时。例如,如果我想选择过去的90天,我可以这样写 WHERE DATE((CC01*100+YR01)| |'-| | | MO01 | |'-| | | DY01)>=当前日期
- 世纪:CC01:20
- 年份:YR01:13
- 月份:MO01:7
- 日期:DY01:22
date((CC01*100+YR01)| |'-'| | MO01 | |'-'| | DY01)
问题是当我需要过滤一系列日期时。例如,如果我想选择过去的90天,我可以这样写
WHERE DATE((CC01*100+YR01)| |'-| | | MO01 | |'-| | | DY01)>=当前日期-90天
这里的问题是性能。我正在寻找一种有效的方法来编写这个公式,将函数限制在方程的右侧
下面是一个适用于今天日期的示例(我不需要担心世纪,我省略了一些细节):
其中CC01=20,YR01>=右(年(当前日期-7天),2)和MO01>=月(当前日期-7天),DY01>=天(当前日期-7天)
这只会起作用,因为回溯7天会使我们保持当前月份和年份。我也不希望有大量的and和OR(如果可能)。您有权修改DB模式吗? 如果是这样,您可以考虑日期的“生成列”:
您有权修改数据库模式吗? 如果是这样,您可以考虑日期的“生成列”:
您要查询的日期范围长度是否有限制? 对于短范围,您可以生成详细的动态SQL,如:
WHERE
(CC01 = 20 AND YR01 = 07 AND MO01 = 02 AND DY01 = 01)
OR (CC01 = 20 AND YR01 = 07 AND MO01 = 03 AND DY01 = 04)
OR (CC01 = 20 AND YR01 = 07 AND MO01 = 04 AND DY01 = 03)
您必须分析较长的查询是否可以补偿较快的查找(我的直觉说,跨越数亿条记录的函数调用将较慢,尽管直觉永远不可信)。您将查询的日期范围长度是否有限制? 对于短范围,您可以生成详细的动态SQL,如:
WHERE
(CC01 = 20 AND YR01 = 07 AND MO01 = 02 AND DY01 = 01)
OR (CC01 = 20 AND YR01 = 07 AND MO01 = 03 AND DY01 = 04)
OR (CC01 = 20 AND YR01 = 07 AND MO01 = 04 AND DY01 = 03)
你必须分析一下,看看较长的查询是否能弥补较快的查找速度(我的直觉说,跨越数亿条记录的函数调用会较慢,尽管直觉永远不可信)。我相信我可能已经找到了解决方案
CC01 = 20
AND
YR01 >= RIGHT(YEAR(CURRENT DATE - 220 DAYS),2)
AND NOT
(
YR01 = RIGHT(YEAR(CURRENT DATE - 220 DAYS),2)
AND
MO01 = MONTH(CURRENT DATE - 220 DAYS)
AND
DY01 < DAY(CURRENT DATE - 220 DAYS)
)
AND NOT
(
YR01 = RIGHT(YEAR(CURRENT DATE - 220 DAYS),2)
AND
MO01 < MONTH(CURRENT DATE - 220 DAYS)
)
CC01=20
及
YR01>=右侧(年份(当前日期-220天),2)
而不是
(
YR01=右侧(年份(当前日期-220天),2)
及
MO01=月份(当前日期-220天)
及
DY01<天(当前日期-220天)
)
而不是
(
YR01=右侧(年份(当前日期-220天),2)
及
MO01<月份(当前日期-220天)
)
我相信我已经找到了解决办法
CC01 = 20
AND
YR01 >= RIGHT(YEAR(CURRENT DATE - 220 DAYS),2)
AND NOT
(
YR01 = RIGHT(YEAR(CURRENT DATE - 220 DAYS),2)
AND
MO01 = MONTH(CURRENT DATE - 220 DAYS)
AND
DY01 < DAY(CURRENT DATE - 220 DAYS)
)
AND NOT
(
YR01 = RIGHT(YEAR(CURRENT DATE - 220 DAYS),2)
AND
MO01 < MONTH(CURRENT DATE - 220 DAYS)
)
CC01=20
及
YR01>=右侧(年份(当前日期-220天),2)
而不是
(
YR01=右侧(年份(当前日期-220天),2)
及
MO01=月份(当前日期-220天)
及
DY01<天(当前日期-220天)
)
而不是
(
YR01=右侧(年份(当前日期-220天),2)
及
MO01<月份(当前日期-220天)
)
定义要转换为日期的函数
CREATE FUNCTION parts2date (cc int, yy int, mm int, dd int ) returns date
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
BEGIN
RETURN DATE( RIGHT(DIGITS(cc),2)||RIGHT(DIGITS(yy),w)||'-'
||RIGHT(DIGITS(mm),2)||'-'||RIGHT(DIGITS(dd),2) );
END;
您可以添加一个条件处理程序,以便在出现错误时返回null。定义一个函数以转换为日期
CREATE FUNCTION parts2date (cc int, yy int, mm int, dd int ) returns date
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
BEGIN
RETURN DATE( RIGHT(DIGITS(cc),2)||RIGHT(DIGITS(yy),w)||'-'
||RIGHT(DIGITS(mm),2)||'-'||RIGHT(DIGITS(dd),2) );
END;
您可以添加一个条件处理程序,以便在出现错误时返回null。将其作为额外列选择,这样您只需定义一次?并在where子句中使用该列。也许将日期转换为UNIX时间戳(整数)更容易些,将
限制在val1和val2之间我遇到的问题是表中有数亿条记录。表值上的任何函数都将永远需要处理,并且会占用太多的临时空间。您已经提供了公式。我只有对此数据源的读取权限,将其选择为额外列,因此您只需定义一次?并在where子句中使用该列。也许将日期转换为UNIX时间戳(整数)更容易些,将限制在val1和val2之间我遇到的问题是表中有数亿条记录。表值上的任何函数都将永远需要处理,并且会占用太多的临时空间。您已经提供了公式。我只有对此数据源的读取权限。很遗憾,没有,访问权限是只读的。在我看来,任何解决方案都必须发生在WHERE语句中。不幸的是,没有,访问是只读的。在我看来,任何解决方案都必须在WHERE语句中进行。不幸的是,日期范围必须是动态的。如果您的日期范围限制在几百个,而您的DB表只有几亿个,那么最好是按照请求的日期而不是按DB行进行额外处理。是的,我的意思是在数据库中调用的任何代码中生成SQL查询,或者添加一个包含两个日期并生成SQL字符串的存储过程,如果所有这些都需要在DBa存储过程中生成,就像这样,除了在while循环中,您可以添加一个新的或。。。子句到字符串不幸的是,日期范围需要是动态的。如果您的日期范围限制在几百个,而您的DB表只有几亿个,那么按照请求的日期而不是按DB行进行额外处理肯定会更好。是的,我的意思是在数据库中调用的任何代码中生成SQL查询,或者添加一个包含两个日期并生成SQL字符串的存储过程,如果所有这些都需要在DBa存储过程中生成,就像这样,除了在while循环中,您可以添加一个新的或。。。