我正在尝试重写最初为Vertica编写的一段SQL代码。 Vertica具有AGE_IN_YEARS()
内置功能,非常适合提高年龄。但是,现在,我需要找到一种方法使其在Snowflake中工作,而我做到了。
在Snowflake中替换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子句中编写此案例
答案 0 :(得分:2)
问题是当我必须在WHERE子句中使用它时。
如何将年龄添加到dateofbirth
上?
where dateadd(year, minage, dateofbirth) <= current_date and
dateadd(year, maxage + 1, dateofbirth) > current_date
答案 1 :(得分:1)
不使用函数来计算年龄,而只是将其加入您喜欢的数据即可:
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中更改所有行的user.dob一次更改范围时间。根据假设,您的用户数超过了范围数,并且如果两个用户均小于1000,则以太币没有问题。
答案 2 :(得分:0)
如果您的年龄范围表中有“年龄”列,并且您希望将每个客户/参与者的年龄与年龄范围表的最小和最大范围进行比较,那么您可以简单地通过两种方式进行操作。
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