在 SELECT 子句中重写相关子查询的最有效方法是什么?
What is the most performant way to rewrite a correlated subquery in the SELECT clause?
我正在尝试统计用户是否在三个时间范围内访问过网站:
- 过去 30 天
- 31 到 60 天之间
- 61 到 90 天之间
我正在使用 Netezza,它不支持 SELECT 子句中的相关子查询。请参阅 Rextester 以获取必须重写以不使用相关子查询的成功查询:http://rextester.com/JGR62033
示例数据:
| user_id | last_visit | num_days_since_2017117 |
|---------|------------|------------------------|
| 1234 | 2017-11-02 | 15.6 |
| 1234 | 2017-09-30 | 48.6 |
| 1234 | 2017-09-03 | 75.0 |
| 1234 | 2017-08-21 | 88.0 |
| 9876 | 2017-10-03 | 45.0 |
| 9876 | 2017-07-20 | 120.0 |
| 5545 | 2017-09-15 | 63.0 |
期望输出:
| user_id | last_30 | btwn_31_60 | btwn_61_90 |
|---------|---------|------------|------------|
| 1234 | 1 | 1 | 1 |
| 5545 | 0 | 0 | 1 |
| 9876 | 0 | 1 | 0 |
我不知道您使用的具体 DBMS,但如果它支持 CASE
或等效的,您就不需要相关的子查询;你可以结合使用 SUM()
和 CASE
.
当然,在您的 DBMS 中未经测试,但它应该给您一个起点:
SELECT
user_id,
SUM(CASE WHEN num_days <= 30 then 1 else 0 end) as last_30,
SUM(CASE WHEN num_days > 30 AND numdays < 61 then 1 else 0 end) as btwn_31_60,
SUM(CASE WHEN num_days >= 61 then 1 else 0 end) as btwn_61_90
FROM
YourTableName -- You didn't provide a tablename
GROUP BY
user_id
由于您的值是浮点数而不是整数,您可能需要调整用于日期范围的值以满足您的特定要求。
这是条件聚合的一种方式,Rextester:
select
user_id
,MAX(case when '2017-11-17'-visit_date <=30
then 1
else 0
end) as last_30
,MAX(case when '2017-11-17'-visit_date >=31
and '2017-11-17'-visit_date <=60
then 1
else 0
end) as between_31_60
,MAX(case when '2017-11-17'-visit_date >=61
and '2017-11-17'-visit_date <=90
then 1
else 0
end) as between_61_90
from
visits
group by user_id
order by user_id
我正在尝试统计用户是否在三个时间范围内访问过网站:
- 过去 30 天
- 31 到 60 天之间
- 61 到 90 天之间
我正在使用 Netezza,它不支持 SELECT 子句中的相关子查询。请参阅 Rextester 以获取必须重写以不使用相关子查询的成功查询:http://rextester.com/JGR62033
示例数据:
| user_id | last_visit | num_days_since_2017117 |
|---------|------------|------------------------|
| 1234 | 2017-11-02 | 15.6 |
| 1234 | 2017-09-30 | 48.6 |
| 1234 | 2017-09-03 | 75.0 |
| 1234 | 2017-08-21 | 88.0 |
| 9876 | 2017-10-03 | 45.0 |
| 9876 | 2017-07-20 | 120.0 |
| 5545 | 2017-09-15 | 63.0 |
期望输出:
| user_id | last_30 | btwn_31_60 | btwn_61_90 |
|---------|---------|------------|------------|
| 1234 | 1 | 1 | 1 |
| 5545 | 0 | 0 | 1 |
| 9876 | 0 | 1 | 0 |
我不知道您使用的具体 DBMS,但如果它支持 CASE
或等效的,您就不需要相关的子查询;你可以结合使用 SUM()
和 CASE
.
当然,在您的 DBMS 中未经测试,但它应该给您一个起点:
SELECT
user_id,
SUM(CASE WHEN num_days <= 30 then 1 else 0 end) as last_30,
SUM(CASE WHEN num_days > 30 AND numdays < 61 then 1 else 0 end) as btwn_31_60,
SUM(CASE WHEN num_days >= 61 then 1 else 0 end) as btwn_61_90
FROM
YourTableName -- You didn't provide a tablename
GROUP BY
user_id
由于您的值是浮点数而不是整数,您可能需要调整用于日期范围的值以满足您的特定要求。
这是条件聚合的一种方式,Rextester:
select
user_id
,MAX(case when '2017-11-17'-visit_date <=30
then 1
else 0
end) as last_30
,MAX(case when '2017-11-17'-visit_date >=31
and '2017-11-17'-visit_date <=60
then 1
else 0
end) as between_31_60
,MAX(case when '2017-11-17'-visit_date >=61
and '2017-11-17'-visit_date <=90
then 1
else 0
end) as between_61_90
from
visits
group by user_id
order by user_id