为什么这个子查询在 Snowflake 中不起作用?

Why is this subquery not working in Snowflake?

我有一个子查询在 Snowflake 中不起作用。我收到此错误:

SQL compilation error: Unsupported subquery type cannot be evaluated

当我运行这个查询中的子查询时它不起作用。但是,我需要包含此子查询,以便考虑将在 case 语句中使用的“状态”列。

有人可以帮忙吗?

create table TBL_A (
    number_id int, country varchar(50), status varchar(50), datetime date
);
insert into TBL_A values 
(121144, 'USA', 'CLAIMED', '2021-10-10'),
(121144, 'USA', 'BOUGHT', '2021-10-11'),
(121144, 'USA', 'RETURNED', '2021-10-12'),
(121144, 'AU', 'CLAIMED', '2021-09-10'),
(121144, 'AU', 'BOUGHT', '2021-09-11');

create table TBL_B  (
    number_id int, country varchar, status varchar, 
    claimed_date date, bought_date date, returned_date date
);

查询我需要运行:

insert into TBL_B (number_id, country, status, claimed_date, bought_date, returned_date)
select
    w.number_id, w.country, w.status
    , case w.status when 'CLAIMED' then w.datetime else '2999-12-31' end claimed_date
    , case w.status when 'BOUGHT' then w.datetime else '2999-12-31' end bought_date
    , case w.status when 'RETURNED' then w.datetime else '2999-12-31' end returned_date
from
(
    select x.*, (select z.status from TBL_A z where z.number_id=x.number_id and z.country=x.country and z.datetime=x.datetime) status
    from
    (
        select a.number_id, a.country, max(datetime) as datetime
        from TBL_A a
        group by a.number_id, a.country
    ) x

可以使用横向重写查询:

select x.*, z.status
from (select a.number_id, a.country, max(datetime) as datetime
     from TBL_A a
     group by a.number_id, a.country
) x
left join lateral(select z.status 
                 from TBL_A z 
                 where z.number_id=x.number_id 
                   and z.country=x.country 
                   and z.datetime=x.datetime) z;


更重要的部分是查询应该做什么。如果目标是获得最新状态,那么 QUALIFY 是最直接的实现方式:

-- insert into
select  number_id, country, datetime, status
from TBL_A
qualify  rank() over (partition by number_id, country order by datetime desc) = 1;


如果目标是获取最新状态以及每个状态的日期,那么条件聚合是可行的方法:

select a.number_id, a.country,
   (array_agg(status) within group(order by datetime desc)[0])::varchar as latest_status,
   coalesce(max(case when status = 'CLAIMED'  THEN datetime END),'2999-12-31'::date) as claimed_date,
   coalesce(max(case when status = 'BOUGHT'   THEN datetime END),'2999-12-31'::date) as bought_date,
   coalesce(max(case when status = 'RETURNED' THEN datetime END),'2999-12-31'::date) as returned_date
from TBL_A a
group by a.number_id, a.country;

输出: