如何在snowflake的where子句中编写case语句

aiqt4smr  于 2021-08-13  发布在  Java
关注(0)|答案(3)|浏览(415)

我试图重写一段最初为vertica编写的sql代码。vertica有 AGE_IN_YEARS() 内置的功能,这是伟大的获得某人的年龄。但是,现在,我需要想办法让它在雪花中工作,我做到了。
替换的等价语句 AGE_IN_YEARS(DateOfBirth) 在雪花中可以是:

case when dateadd(year, datediff(years, DateOfBirth, CURRENT_DATE), DateOfBirth) > CURRENT_DATE
then datediff(years, DateOfBirth, CURRENT_DATE) -1
else datediff(years, DateOfBirth, CURRENT_DATE)
end as AGE

问题是我必须在where子句中使用这个。最初的vertica代码是:

SELECT name, dob,
(SELECT AgeRangeCode
   FROM AgeRangeTable
   WHERE AGE_IN_YEARS(DateOfBirth) BETWEEN MinAge AND MaxAge) AS AgeRangeCode,
CURRENT_DATE as TODAY
from MemberInfoTable

如果我加上 AGE_IN_YEARS() 替换上述查询,我得到
sql编译错误:无法计算不支持的子查询类型
我该如何在where子句中写这个例子呢

cig3rfwq

cig3rfwq1#

问题是我必须在where子句中使用这个。
把年龄加上去怎么样 dateofbirth 相反呢?

where dateadd(year, minage, dateofbirth) <= current_date and
      dateadd(year, maxage + 1, dateofbirth) > current_date
jaql4c8m

jaql4c8m2#

不使用函数计算年龄,只需加入您喜欢的数据即可:

with age_range_table as (
    select * from values (0,16, 'A'),(16,18, 'B'),(18,1000, 'C') v(min_age, max_age, age_range_code)
), member_info_table as (
    select name, dob::date as dob from values ('user_80s', '1980-01-01'),('user_90s', '1990-01-01'),('user_10s', '2010-01-01') v(name, dob)
)
select m.name,
    m.dob,
    a.age_range_code
from member_info_table AS m
join age_range_table AS a
    ON m.dob < dateadd('years',-a.min_age, current_date)
    AND m.dob >= dateadd('years',-a.max_age, current_date);

给:

NAME    DOB AGE_RANGE_CODE
user_80s    1980-01-01  C
user_90s    1990-01-01  C
user_10s    2010-01-01  A

但在where子句中进行函数调用有点恶心。。

with age_range_table as (
    select * 
    from values 
        (0,16, 'A'),
        (16,18, 'B'),
        (18,1000, 'C') 
        v(min_age, max_age, age_range_code)
), member_info_table as (
    select name, dob::date as dob 
    from values 
       ('user_80s', '1980-01-01'),
       ('user_90s', '1990-01-01'),
       ('user_10s', '2010-01-01')
       v(name, dob)
), today_age_range_table as (
    select age_range_code
        ,dateadd('years',-min_age, current_date) as range_end_date
        ,dateadd('years',-max_age, current_date) as range_start_date
    from age_range_table
)
select m.name,
    m.dob,
    a.age_range_code
from member_info_table AS m
join today_age_range_table AS a
    ON m.dob < a.range_end_date
    AND m.dob >= a.range_start_date;

贷方注解:这是与gordon的解决方案相同的解决方案,但它是显式显示的。并且范围逻辑更改为在cte verse中更改所有行的user.dob一次范围时间。基于这样的假设,你拥有的用户多于范围,如果两者都低于1000,你就没有问题了。

kqhtkvqz

kqhtkvqz3#

如果您在agerange表中有age列,并且您希望将每个客户/参与者的年龄与之进行比较,并且还希望在age range表的min和max范围内进行比较,那么您可以通过两种方式简单地进行比较。

SELECT name, dob,
       [AgeRangeCode] = (SELECT AgeRangeCode FROM AgeRangeTable WHERE DATEDIFF(Year,mi.dob,CURRENT_DATE) = mi.age 
                                                         AND DATEDIFF(Year,mi.dob,CURRENT_DATE) BETWEEN MinAge AND MaxAge),
       CURRENT_DATE as TODAY
from MemberInfoTable mi

或者像下面这样简单的连接

SELECT mi.name, mi.dob, art.AgeRangeCode,
       CURRENT_DATE as TODAY
FROM  MemberInfoTable mi
JOIN  AgeRangeTable art ON art.age = DATEDIFF(Year,mi.dob,CURRENT_DATE)
WHERE DATEDIFF(Year,mi.dob,CURRENT_DATE) BETWEEN art.MinAge AND art.MaxAge

相关问题