【问题标题】:Teradata SQL returning previous two months, based on CURRENT_DATETeradata SQL 返回前两个月,基于 CURRENT_DATE
【发布时间】:2020-06-03 09:02:47
【问题描述】:

TLDR: 我想根据 CURRENT_DATE 在 Teradata 中获取前两个月的表。目前我只能得到上个月:

SELECT 
TO_CHAR(ADD_MONTHS(CURRENT_DATE  - EXTRACT(DAY FROM CURRENT_DATE )+1, -1), 'YYYY-MM') MM;

预期输出是:

+--------+
|   MM   |
+--------+
| 2020-01|
| 2019-12|
+--------+

加长版: 我想要一些东西,可以在像这样的更大查询中使用,对一年中的每一天都有效,而无需对日期进行硬编码。带有硬编码日期的更大查询如下所示:

AND TO_CHAR(SOME_DATE, 'YYYY-MM') IN ('2020-01', '2019-12')

而且效果很好。以下返回结果正常,但仅限 1 个月。

AND TO_CHAR(SOME_DATE, 'YYYY-MM') IN 
(
TO_CHAR(ADD_MONTHS(CURRENT_DATE  - EXTRACT(DAY FROM CURRENT_DATE )+1, -1), 'YYYY-MM')
)

尝试添加逗号并添加与-2相同的行,不起作用

AND TO_CHAR(SOME_DATE, 'YYYY-MM') IN 
(
TO_CHAR(ADD_MONTHS(CURRENT_DATE  - EXTRACT(DAY FROM CURRENT_DATE )+1, -1), 'YYYY-MM'),
TO_CHAR(ADD_MONTHS(CURRENT_DATE  - EXTRACT(DAY FROM CURRENT_DATE )+1, -2), 'YYYY-MM')
)

错误是:

SELECT 失败 3706:语法错误:预期在 ')' 和 '.' 之间。

【问题讨论】:

  • 基于已删除的答案/cmets:是不是你想要的简单联合,两行以 2020-01 和 2019-02 作为值?
  • @Turo - 实际上,我想要一些可以在更大的查询中使用的东西,例如:AND SOME_DATE IN ('2020-01', '2019-12'),无需对日期进行硬编码。
  • UNION 会成功,但两者之间有什么问题?
  • @Turo - 我想他们两个都没有问题,如果他们可以提供所需的答案,而无需硬编码。
  • Teradata 不允许在IN 中计算表达式(对于单个条件,它可能转换为=),不知道为什么存在这种愚蠢的限制。

标签: sql performance date teradata


【解决方案1】:

尝试使用子查询:

select * from table where date in 
(SELECT To_char(ADD_MONTHS(CURRENT_DATE , -2),'YYYY-MM') MM
union 
SELECT To_char(ADD_MONTHS(CURRENT_DATE , -1),'YYYY-MM') MM
);

【讨论】:

  • 我已经更改了我的大查询的IN 部分,但它给了我一个错误,3888 - A SELECT for UNION, INTERSECT or MINUS must reference a table.
  • 对,对于这些情况,在 DB2 中是 SYSDUMMY,在 Orcale 中是双重的,但我不知道 Teradata
  • 对于 teradta,没有虚拟表。只需选择1;会给你 1. 选择 1 其中 1= 1;也会给你结果。
【解决方案2】:

为什么不使用或

select * from table where 
   (SOME_DATE =  To_char(ADD_MONTHS(CURRENT_DATE , -2),'YYYY-MM') OR 
   SOME_DATE =  To_char(ADD_MONTHS(CURRENT_DATE , -1),'YYYY-MM'))

【讨论】:

  • SOME_DATE 是一个字符,因此它应该匹配这两个。
  • 然后是或。
  • Hm... 这可能会起作用,但 SOME_DATE 会计算两次,会减慢速度。看看更新的问题,我添加了更多信息。
  • 因此两者之间没有有效值,并且之前的答案会起作用。但是你想要检查日期是否在 2019 年 12 月 1 日(上个月的第一天)和 2020 年 1 月 31 日(上个月的最后一个月)之间,对吗?
  • 嗯,目前查询运行完美,如下所示:AND TO_CHAR(SOME_DATE, 'YYYY-MM') IN ('2020-01', '2019-12'),我唯一想要的是将 ('2020-01', '2019-12') 替换为计算值而不是硬编码值。我不想更改查询的结构。
【解决方案3】:

你的计算太复杂了:

TO_CHAR(ADD_MONTHS(CURRENT_DATE  - EXTRACT(DAY FROM CURRENT_DATE )+1, -1), 'YYYY-MM')
= To_Char(Add_Months(Current_Date, -1), 'YYYY-MM')

TO_CHAR(ADD_MONTHS(CURRENT_DATE  - EXTRACT(DAY FROM CURRENT_DATE )+1, -2), 'YYYY-MM')
= To_Char(Add_Months(Current_Date, -2), 'YYYY-MM')

但是您比较 YYYY_MM 的方法是完全错误的。

Assumimg SOME_DATE 实际上是一个 DATE CAST 将它转换为一个字符串会导致丢失统计信息和全表扫描,如果该表在该日期之前是分区的。两者都可能导致糟糕的计划。

您应该保持日期列原样并在 CURRENT_DATE 进行所有计算:

WHERE som_date BETWEEN Trunc(Add_Months(Current_Date, -2), 'mon')
                   AND Current_Date - Extract(DAY From Current_Date)

【讨论】:

  • AND Last_Day(Current_Date) 会给出当前月份,我想要“上一个”和“上一个上一个”。但这个主意不错。
猜你喜欢
  • 2021-09-23
  • 2021-08-30
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多