为什么这个子查询在 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;
输出:
我有一个子查询在 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;
输出: