【问题标题】:Syntax error using the WITH clause使用 WITH 子句的语法错误
【发布时间】:2016-11-01 19:35:29
【问题描述】:

我正在尝试设置一个包含一系列季度日期的 CTE 表。
查询返回 [42601] ERROR: syntax error at or near "values" Position: 38

with q(qqyy, firstday, lastday) as (
values
('Q4_10', '09-30-2010', '12-31-2010'),
('Q1_11', '12-31-2010', '03-31-2011'),
('Q2_11', '03-31-2011', '06/30/2011'),
('Q3_11', '06/30/2011', '09/30/2011'),
('Q4_11', '09/30/2011', '12/31/2011'),
('Q1_12', '12/31/2011', '03/31/2012'),
('Q2_12', '03/31/2012', '06/30/2012'),
('Q3_12', '06/30/2012', '09/30/2012'),
('Q4_12', '09/30/2012', '12/31/2012'),
('Q1_13', '12/31/2012', '03/31/2013'),
('Q2_13', '03/31/2013', '06/30/2013'),
('Q3_13', '06/30/2013', '09/30/2013'),
('Q4_13', '09/30/2013', '12/31/2013'),
('Q1_14', '12/31/2013', '03/31/2014'),
('Q2_14', '03/31/2014', '06/30/2014'),
('Q3_14', '06/30/2014', '09/30/2014'),
('Q4_14', '09/30/2014', '12/31/2014'),
('Q1_15', '12/31/2014', '03/31/2015'),
('Q2_15', '03/31/2015', '06/30/2015'),
('Q3_15', '06/30/2015', '09/30/2015'),
('Q4_15', '09/30/2015', '12/31/2015'),
('Q1_16', '12/31/2015', '03/31/2016'),
('Q2_16', '03/31/2016', '06/30/2016'),
('Q3_16', '06/30/2016', '09/30/2016'),
('Q4_16', '09/30/2016', '12/31/2016')
  )

SELECT q.qqyy, cobrand_id, sum(calc)
into   temp_08.cmg_calc
from temp_08.cmg s 
join q on 
s.transaction_date >= q.firstday 
and s.transaction_date <= q.lastday
GROUP BY q.qqyy, cobrand_id;

由于 Redshift 使用旧版本的 postgresql (http://docs.aws.amazon.com/redshift/latest/dg/c_unsupported-postgresql-features.html),上述查询似乎卡在“值”上。但由于某种原因,以下也使用“值”的查询工作正常。知道如何使用 redshift 使上述查询工作吗?

 create table temp_08.cmgquarters (
quarter_col text
  , date_from   date
  , date_to     date
);


 insert into temp_08.cmgquarters
   values
('Q4_10', '09-30-2010', '12-31-2010'),
('Q1_11', '12-31-2010', '03-31-2011'),
('Q2_11', '03-31-2011', '06/30/2011'),
('Q3_11', '06/30/2011', '09/30/2011'),
('Q4_11', '09/30/2011', '12/31/2011'),
('Q1_12', '12/31/2011', '03/31/2012'),
('Q2_12', '03/31/2012', '06/30/2012'),
('Q3_12', '06/30/2012', '09/30/2012'),
('Q4_12', '09/30/2012', '12/31/2012'),
('Q1_13', '12/31/2012', '03/31/2013'),
('Q2_13', '03/31/2013', '06/30/2013'),
('Q3_13', '06/30/2013', '09/30/2013'),
('Q4_13', '09/30/2013', '12/31/2013'),
('Q1_14', '12/31/2013', '03/31/2014'),
('Q2_14', '03/31/2014', '06/30/2014'),
('Q3_14', '06/30/2014', '09/30/2014'),
('Q4_14', '09/30/2014', '12/31/2014'),
('Q1_15', '12/31/2014', '03/31/2015'),
('Q2_15', '03/31/2015', '06/30/2015'),
('Q3_15', '06/30/2015', '09/30/2015'),
('Q4_15', '09/30/2015', '12/31/2015'),
('Q1_16', '12/31/2015', '03/31/2016'),
('Q2_16', '03/31/2016', '06/30/2016'),
('Q3_16', '06/30/2016', '09/30/2016'),
('Q4_16', '09/30/2016', '12/31/2016');

【问题讨论】:

  • 除了应该工作的无效日期文字。
  • @a_horse_with_no_name - 当我在您的链接中运行脚本时,它似乎工作正常。但是当我在我的 IDE 中运行脚本时,我得到了同样的错误:[42601] 错误:“值”位置或附近的语法错误:41。为了它的价值,我使用的是 JetBrains 的 DataGrip IDE,它使用 PostgreSQL .有什么想法吗?
  • 也许你的 IDE 太聪明了,不知道公用表表达式。它可以与psql 一起使用吗?
  • 您没有使用 Postgres,您使用的是 Redshift(它基于一个 真正 旧的和过时的 Postgres 版本)。根据Redshift manual values() 子句作为常量表不受支持

标签: sql amazon-redshift


【解决方案1】:

由于 Redshift 不支持将 values() 作为“表替换”,您需要将其重写为 union

with q(qqyy, firstday, lastday) as (
  select 'Q4_10', '09-30-2010', '12-31-2010' union all
  select 'Q1_11', '12-31-2010', '03-31-2011' union all
  ....
)
SELECT ...;

但是,您应该使用正确的 DATE 文字:

with q(qqyy, firstday, lastday) as (
  select 'Q4_10', DATE '2010-09-30', DATE '2010-12-31' union all
  select 'Q1_11', DATE '2010-12-31', DATE '2011-03-31' union all
  ....
)
SELECT ...;

【讨论】:

  • @a_horse_with_no_name 不幸的是,此解决方案仍然返回 [42601] 错误:“值”位置或附近的语法错误位置:37
  • @ZJAY:抱歉,复制和粘贴错误。 values 当然必须完全删除
【解决方案2】:

我不太了解 Postgres,但是对于 SQL-Server,您不能像直接使用表一样使用 VALUES。您必须使用括号括起来并提供带有列名的表别名来定义派生表。

这将是这样的:

with q as (
select * from
(
    values
    ('Q4_10', '09-30-2010', '12-31-2010'),
    ('Q1_11', '12-31-2010', '03-31-2011'),
    ('Q2_11', '03-31-2011', '06/30/2011'),
    ('Q3_11', '06/30/2011', '09/30/2011'),
    ('Q4_11', '09/30/2011', '12/31/2011'),
    ('Q1_12', '12/31/2011', '03/31/2012'),
    ('Q2_12', '03/31/2012', '06/30/2012'),
    ('Q3_12', '06/30/2012', '09/30/2012'),
    ('Q4_12', '09/30/2012', '12/31/2012'),
    ('Q1_13', '12/31/2012', '03/31/2013'),
    ('Q2_13', '03/31/2013', '06/30/2013'),
    ('Q3_13', '06/30/2013', '09/30/2013'),
    ('Q4_13', '09/30/2013', '12/31/2013'),
    ('Q1_14', '12/31/2013', '03/31/2014'),
    ('Q2_14', '03/31/2014', '06/30/2014'),
    ('Q3_14', '06/30/2014', '09/30/2014'),
    ('Q4_14', '09/30/2014', '12/31/2014'),
    ('Q1_15', '12/31/2014', '03/31/2015'),
    ('Q2_15', '03/31/2015', '06/30/2015'),
    ('Q3_15', '06/30/2015', '09/30/2015'),
    ('Q4_15', '09/30/2015', '12/31/2015'),
    ('Q1_16', '12/31/2015', '03/31/2016'),
    ('Q2_16', '03/31/2016', '06/30/2016'),
    ('Q3_16', '06/30/2016', '09/30/2016'),
    ('Q4_16', '09/30/2016', '12/31/2016')
  ) AS tbl(qqyy, firstday, lastday)
)
SELECT *
from q

注意

你处于高度危险之中!

  • 您正在使用文化相关的日期格式。这可能适用于您的系统,但在另一个系统上会中断......
  • 此外,您甚至不一致!
  • 您的VALUES 将您的日期值作为字符串提供。

在 SQL-Server 中,我建议使用未分隔的 ISO8601 或 - 我最喜欢的 - ODBC。但我确信 Postgres 中的文字日期也有与文化无关的格式。

我建议让 CTE 以类型值返回或使用带有类型列的临时表。

【讨论】:

  • 在 Postgres 中你可以像这样使用values
  • 在 Postgres 中最好使用 ANSI 日期文字,例如date '2016-12-31'
  • @a_horse_with_no_name 再次感谢,我确信每个 RDBMS 都有一个 best 文字日期格式。无论如何,2016-12-31 似乎与ISO 8601 非常接近,但与上面提供的(混合)格式相差甚远......
  • 这就是 SQL 标准定义日期文字的方式——理论上每个 DBMS 都应该尊重这一点(但微软从未真正关心过该标准)
  • 谢谢@a_horse_with_no_name。使用我上面使用的日期有什么缺点?
猜你喜欢
  • 1970-01-01
  • 2016-03-10
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 2021-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多