【问题标题】:Why is this subquery not working in Snowflake?为什么这个子查询在 Snowflake 中不起作用?
【发布时间】:2021-12-20 10:52:42
【问题描述】:

我有一个在 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

【问题讨论】:

标签: sql snowflake-cloud-data-platform snowflake-schema


【解决方案1】:

查询可以使用横向重写:

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;

输出:

【讨论】:

  • 您好!谢谢,这有帮助!但是,当没有声明或购买状态时,我将如何考虑这一点?如果只有一个状态,那么它也应该被标记为订单
  • @lalaland 如果缺少值,COALESCE 会处理它。这里通过将值设置为 2999-12-31。如果它应该是不同的,可以调整:COALESCE(max(case when status = 'CLAIMED' THEN datetime END),max(case when status = 'BOUGHT' THEN datetime END),'2999-12-31'::date)
  • 非常感谢您的帮助!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 1970-01-01
  • 2023-03-19
相关资源
最近更新 更多