Redshift无LIMIT语句却报LIMIT语法错误的原因排查
在Amazon Redshift Serverless中SQL查询报LIMIT语法错误的排查方案
运行以下SQL查询时反复失败:
with ssr as (select s_store_id, sum(sales_price) as sales, sum(profit) as profit, sum(return_amt) as returns, sum(net_loss) as profit_loss from ( select ss_store_sk as store_sk, ss_sold_date_sk as date_sk, ss_ext_sales_price as sales_price, ss_net_profit as profit, cast(0 as decimal(7,2)) as return_amt, cast(0 as decimal(7,2)) as net_loss from store_sales union all select json_data.sr_customer_sk::bigint as store_sk, sr_returned_date_sk as date_sk, cast(0 as decimal(7,2)) as sales_price, cast(0 as decimal(7,2)) as profit, json_data.sr_return_amt::decimal(7,2) as return_amt, json_data.sr_net_loss::decimal(7,2) as net_loss from store_returns_json ) salesreturns, date_dim, store where date_sk = d_date_sk and d_date between cast('1998-08-04' as date) and dateadd(day, 14, cast('1998-08-04' as date)) and store_sk = s_store_sk group by s_store_id) , csr as (select cp_catalog_page_id, sum(sales_price) as sales, sum(profit) as profit, sum(return_amt) as returns, sum(net_loss) as profit_loss from ( select cs_catalog_page_sk as page_sk, cs_sold_date_sk as date_sk, cs_ext_sales_price as sales_price, cs_net_profit as profit, cast(0 as decimal(7,2)) as return_amt, cast(0 as decimal(7,2)) as net_loss from catalog_sales union all select cr_catalog_page_sk as page_sk, cr_returned_date_sk as date_sk, cast(0 as decimal(7,2)) as sales_price, cast(0 as decimal(7,2)) as profit, cr_return_amount as return_amt, cr_net_loss as net_loss from catalog_returns ) salesreturns, date_dim, catalog_page where date_sk = d_date_sk and d_date between cast('1998-08-04' as date) and dateadd(day, 14, cast('1998-08-04' as date)) and page_sk = cp_catalog_page_sk group by cp_catalog_page_id) , wsr as (select web_site_id, sum(sales_price) as sales, sum(profit) as profit, sum(return_amt) as returns, sum(net_loss) as profit_loss from ( select ws_web_site_sk as wsr_web_site_sk, ws_sold_date_sk as date_sk, ws_ext_sales_price as sales_price, ws_net_profit as profit, cast(0 as decimal(7,2)) as return_amt, cast(0 as decimal(7,2)) as net_loss from web_sales union all select ws_web_site_sk as wsr_web_site_sk, wr_returned_date_sk as date_sk, cast(0 as decimal(7,2)) as sales_price, cast(0 as decimal(7,2)) as profit, wr_return_amt as return_amt, wr_net_loss as net_loss from web_returns left outer join web_sales on ( wr_item_sk = ws_item_sk and wr_order_number = ws_order_number) ) salesreturns, date_dim, web_site where date_sk = d_date_sk and d_date between cast('1998-08-04' as date) and dateadd(day, 14, cast('1998-08-04' as date)) and wsr_web_site_sk = web_site_sk group by web_site_id) select channel as xchannel , id as xid , sum(sales) as xsales , sum(returns) as xreturns , sum(profit) as xprofit from (select 'store channel' as channel , 'store' || s_store_id as id , sales , returns , (profit - profit_loss) as profit from ssr union all select 'catalog channel' as channel , 'catalog_page' || cp_catalog_page_id as id , sales , returns , (profit - profit_loss) as profit from csr union all select 'web channel' as channel , 'web_site' || web_site_id as id , sales , returns , (profit - profit_loss) as profit from wsr ) group by (xchannel,xid) union all select channel as xchannel , 'All' as xid , sum(sales) as xsales , sum(returns) as xreturns , sum(profit) as xprofit from ( select 'store channel' as channel , 'store' || s_store_id as id , sales , returns , (profit - profit_loss) as profit from ssr union all select 'catalog channel' as channel , 'catalog_page' || cp_catalog_page_id as id , sales , returns , (profit - profit_loss) as profit from csr union all select 'web channel' as channel , 'web_site' || web_site_id as id , sales , returns , (profit - profit_loss) as profit from wsr ) group by (xchannel) --order by xchannel,xid ;
报错信息:
Detail: SQL reparse error. Where: syntax error at or near "LIMIT"
问题原因
- Redshift Serverless内部重解析bug:当处理包含多层CTE、UNION ALL且存在重复子查询的复杂语句时,Redshift Serverless的查询优化器会尝试自动添加
LIMIT做预览解析,但这个内部操作会触发语法解析异常,即便代码里没有显式写LIMIT。 - 匿名子查询的解析问题:原查询中最后两个
UNION ALL对应的子查询没有指定别名,Redshift Serverless的解析器对这种匿名子查询的兼容性较差,容易触发解析错误。
修复方案
将重复的子查询逻辑提取为公共CTE,同时为所有子查询添加明确别名,简化查询结构:
with ssr as (select s_store_id, sum(sales_price) as sales, sum(profit) as profit, sum(return_amt) as returns, sum(net_loss) as profit_loss from ( select ss_store_sk as store_sk, ss_sold_date_sk as date_sk, ss_ext_sales_price as sales_price, ss_net_profit as profit, cast(0 as decimal(7,2)) as return_amt, cast(0 as decimal(7,2)) as net_loss from store_sales union all select json_data.sr_customer_sk::bigint as store_sk, sr_returned_date_sk as date_sk, cast(0 as decimal(7,2)) as sales_price, cast(0 as decimal(7,2)) as profit, json_data.sr_return_amt::decimal(7,2) as return_amt, json_data.sr_net_loss::decimal(7,2) as net_loss from store_returns_json ) salesreturns, date_dim, store where date_sk = d_date_sk and d_date between cast('1998-08-04' as date) and dateadd(day, 14, cast('1998-08-04' as date)) and store_sk = s_store_sk group by s_store_id) , csr as (select cp_catalog_page_id, sum(sales_price) as sales, sum(profit) as profit, sum(return_amt) as returns, sum(net_loss) as profit_loss from ( select cs_catalog_page_sk as page_sk, cs_sold_date_sk as date_sk, cs_ext_sales_price as sales_price, cs_net_profit as profit, cast(0 as decimal(7,2)) as return_amt, cast(0 as decimal(7,2)) as net_loss from catalog_sales union all select cr_catalog_page_sk as page_sk, cr_returned_date_sk as date_sk, cast(0 as decimal(7,2)) as sales_price, cast(0 as decimal(7,2)) as profit, cr_return_amount as return_amt, cr_net_loss as net_loss from catalog_returns ) salesreturns, date_dim, catalog_page where date_sk = d_date_sk and d_date between cast('1998-08-04' as date) and dateadd(day, 14, cast('1998-08-04' as date)) and page_sk = cp_catalog_page_sk group by cp_catalog_page_id) , wsr as (select web_site_id, sum(sales_price) as sales, sum(profit) as profit, sum(return_amt) as returns, sum(net_loss) as profit_loss from ( select ws_web_site_sk as wsr_web_site_sk, ws_sold_date_sk as date_sk, ws_ext_sales_price as sales_price, ws_net_profit as profit, cast(0 as decimal(7,2)) as return_amt, cast(0 as decimal(7,2)) as net_loss from web_sales union all select ws_web_site_sk as wsr_web_site_sk, wr_returned_date_sk as date_sk, cast(0 as decimal(7,2)) as sales_price, cast(0 as decimal(7,2)) as profit, wr_return_amt as return_amt, wr_net_loss as net_loss from web_returns left outer join web_sales on ( wr_item_sk = ws_item_sk and wr_order_number = ws_order_number) ) salesreturns, date_dim, web_site where date_sk = d_date_sk and d_date between cast('1998-08-04' as date) and dateadd(day, 14, cast('1998-08-04' as date)) and wsr_web_site_sk = web_site_sk group by web_site_id), -- 提取重复逻辑为公共CTE channel_summary as ( select 'store channel' as channel , 'store' || s_store_id as id , sales , returns , (profit - profit_loss) as profit from ssr union all select 'catalog channel' as channel , 'catalog_page' || cp_catalog_page_id as id , sales , returns , (profit - profit_loss) as profit from csr union all select 'web channel' as channel , 'web_site' || web_site_id as id , sales , returns , (profit - profit_loss) as profit from wsr ) -- 查询明细 select channel as xchannel , id as xid , sum(sales) as xsales , sum(returns) as xreturns , sum(profit) as xprofit from channel_summary group by (xchannel,xid) union all -- 查询渠道汇总 select channel as xchannel , 'All' as xid , sum(sales) as xsales , sum(returns) as xreturns , sum(profit) as xprofit from channel_summary group by (xchannel) --order by xchannel,xid ;
额外建议
- 避免在Redshift Serverless中编写过于冗余的重复子查询,尽量通过公共CTE复用逻辑,降低查询复杂度。
- 如果仍出现类似解析错误,可以尝试将复杂查询拆分为多个步骤,先将中间结果存入临时表,再进行后续聚合查询。
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

