在 Snowflake 中使用 CTE 进行 MATCH_RECOGNIZE

Posted

技术标签:

【中文标题】在 Snowflake 中使用 CTE 进行 MATCH_RECOGNIZE【英文标题】:MATCH_RECOGNIZE with CTE in Snowflake 【发布时间】:2021-07-27 12:10:41 【问题描述】:

我在带有几个 CTE 的查询中使用 MATCH_RECOGNIZE 函数。运行查询时,出现以下错误:

SQL 编译错误:此上下文不支持 MATCH_RECOGNIZE。

在我的查询中,MATCH_RECOGNIZE 前后有几个 CTE,如下所示。

WITH cte1 AS (
SELECT *
FROM dataset
WHERE ID IS NOT NULL AND STATUS IS NOT NULL ),

cte2 AS (
SELECT *
FROM cte1
QUALIFY FIRST_VALUE(STATUS) OVER (PARTITION BY ID ORDER BY CREATED_AT) = 'created' )

mr as (
SELECT *
    FROM cte2
    MATCH_RECOGNIZE (
      PARTITION BY ID
      ORDER BY CREATED_AT
      MEASURES MATCH_NUMBER() AS mn,
               MATCH_SEQUENCE_NUMBER AS msn
      ALL ROWS PER MATCH
      PATTERN (c+m+)
      DEFINE
         c AS status='created'
        ,m AS status='missing_info'
        ,p AS status='pending'
    ) m1
    QUALIFY (ROW_NUMBER() OVER(PARTITION BY mn, ID ORDER BY msn) = 1)
          OR(ROW_NUMBER() OVER(PARTITION BY mn, ID ORDER BY msn DESC)=1)
    ORDER BY ID, CREATED_AT ),

cte3 as (
SELECT *
FROM mr
-- some other operations
)

解决这个问题的理想方法是什么?例如创建常规视图、物化视图或临时表等。我尝试创建视图但出现错误,不确定是否支持。 如何在其他后续 CTE 中使用 MATCH_RECOGNIZE 的结果?

当我添加以下内容时,它会出现此错误:

位置 0 处的语法错误行 xx 意外“创建”。

create view filtered_idents AS

SELECT *
FROM cte2
MATCH_RECOGNIZE (

)

【问题讨论】:

Using “match_recognize” in a Common Table Expression in Snowflake 我已经检查了这篇文章。但是,在 MATCH_RECOGNIZE 之后我确实还有 5 个 CTE,所以不要认为使用子查询会更容易和更有效。有没有其他选择? 【参考方案1】:

这似乎是一个未记录的限制(我要求我们出色的文档团队解决此问题)。

同时,我可以建议将过程划分为步骤以使用match_recognize 结果。

重现错误:

with data as (
    select $1 company, $2 price_date, $3 price
    from values('a',1,10), ('a',2,15)
), cte as (

    select *
    from data match_recognize(
        partition by company
        order by price_date
        measures match_number() as "MATCH_NUMBER"
        all rows per match omit empty matches
        pattern(overavg*)
        define
            overavg as price > avg(price) over (rows between unbounded
                                      preceding and unbounded following)
    )
) 
select * from cte

-- 002362 (0A000): SQL compilation error: MATCH_RECOGNIZE not supported in this context.

两步解决方案:

with data as (
    select $1 company, $2 price_date, $3 price
    from values('a',1,10), ('a',2,15)
)

select *
from data match_recognize(
    partition by company
    order by price_date
    measures match_number() as "MATCH_NUMBER"
    all rows per match omit empty matches
    pattern(overavg*)
    define
        overavg as price > avg(price) over (rows between unbounded
                                  preceding and unbounded following)
)
;


with previous_results as (
    select *
    from table(result_scan(last_query_id()))
)

select * 
from previous_results
;

【讨论】:

一个不错的解决方法。能否以某种方式将其包装在一个视图中(现在我们正在对两个单独的查询进行操作)?理想情况下,我希望有一天会解除这个限制。【参考方案2】:

Kimi,试试我的 sn-p:

SQL 编译错误:位置 0 的第 11 行语法错误意外“先生”。第 17 行语法错误,位置 6 出现意外的“MEASURES”。

第 9 行似乎缺少一个终止逗号。 当我添加一个然后用一个简单的 select 语句完成整个过程时,我不会再遇到语法错误,我只会遇到名称查找错误(当然是预期的)。

【讨论】:

以上是关于在 Snowflake 中使用 CTE 进行 MATCH_RECOGNIZE的主要内容,如果未能解决你的问题,请参考以下文章

Snowflake CTE 中的访问表属性

在 Snowflake SQL 中同时满足两个条件时从 Select 中删除记录

Snowflake 多集群仓库性能 vs 大仓库规模的单仓库

使用 H2 中 CTE 的结果集进行更新

在 SNOWFLAKE 中进行横向展平时重复主键

在 Snowflake 中使用 SQL 进行漏斗分析