使用分析函数计算变化数
Calculating number of changes using Analytic Functions
我想计算每年电子邮件地址的变化次数:
WITH t AS (SELECT 1 as customer_id,'a@gmail.com' as email,2010 as year FROM DUAL
UNION
SELECT 1 as customer_id,'a@yahoo.com' as email,2011 as year FROM DUAL
UNION
SELECT 2 as customer_id,'b@yahoo.com' as email,2010 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@yahoo.com' as email,2012 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@google.com' as email,2012 as year FROM DUAL
)
SELECT year, customer_id,email,
LAG(email,1,0) OVER(ORDER BY email) as email_prev,
sum(case when email <> LAG(sal, 1, 0) OVER (ORDER BY sal) then 1 else 0 end ) changes
FROM t
;
ORA-30483: window 此处不允许使用函数。
结果应该是:
Year changes
==== =======
2010 1
2012 1
2018 20
您的查询不是您真正想要的,是吗? t CTE 中没有 SAL 列,因此查询不会 运行,即使您处理了错误。试试这个查询:
WITH t AS (SELECT 1 as customer_id,'a@gmail.com' as email,2010 as year FROM DUAL
UNION
SELECT 1 as customer_id,'a@yahoo.com' as email,2011 as year FROM DUAL
UNION
SELECT 2 as customer_id,'b@yahoo.com' as email,2010 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@yahoo.com' as email,2012 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@google.com' as email,2012 as year FROM DUAL
),
t1 as ( SELECT year, customer_id,email,
LAG(email,1) OVER(partition by customer_id ORDER BY email) as email_prev
from t)
select year,customer_id,
sum(case when email <> email_prev or email_prev is null then 1 else 0 end ) changes
FROM t1
group by year,customer_id;
这是输出:
YEAR CUSTOMER_ID CHANGES
2010 2 1
2010 1 1
2011 1 1
2012 3 2
WITH t ( customer_id, email, year ) AS (
SELECT 1,'a@gmail.com', 2010 FROM DUAL UNION ALL
SELECT 1,'a@yahoo.com', 2011 FROM DUAL UNION ALL
SELECT 2,'b@yahoo.com', 2010 FROM DUAL UNION ALL
SELECT 3,'c@yahoo.com', 2012 FROM DUAL UNION ALL
SELECT 3,'c@google.com', 2012 FROM DUAL
)
SELECT year,
COUNT(1) AS total_changes,
COUNT( DISTINCT customer_id ) AS num_customers_changed_email
FROM (
SELECT year,
customer_id,
email,
CASE email
WHEN LAG( email, 1 ) OVER( PARTITION BY customer_id ORDER BY year )
THEN 0
ELSE 1
END as has_changed_email
FROM t
)
WHERE has_changed_email = 1
GROUP BY year
ORDER BY year;
输出:
YEAR | TOTAL_CHANGES | NUM_CUSTOMERS_CHANGED_EMAIL
---: | ------------: | --------------------------:
2010 | 2 | 2
2011 | 1 | 1
2012 | 2 | 1
db<>fiddle here
我想计算每年电子邮件地址的变化次数:
WITH t AS (SELECT 1 as customer_id,'a@gmail.com' as email,2010 as year FROM DUAL
UNION
SELECT 1 as customer_id,'a@yahoo.com' as email,2011 as year FROM DUAL
UNION
SELECT 2 as customer_id,'b@yahoo.com' as email,2010 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@yahoo.com' as email,2012 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@google.com' as email,2012 as year FROM DUAL
)
SELECT year, customer_id,email,
LAG(email,1,0) OVER(ORDER BY email) as email_prev,
sum(case when email <> LAG(sal, 1, 0) OVER (ORDER BY sal) then 1 else 0 end ) changes
FROM t
;
ORA-30483: window 此处不允许使用函数。
结果应该是:
Year changes
==== =======
2010 1
2012 1
2018 20
您的查询不是您真正想要的,是吗? t CTE 中没有 SAL 列,因此查询不会 运行,即使您处理了错误。试试这个查询:
WITH t AS (SELECT 1 as customer_id,'a@gmail.com' as email,2010 as year FROM DUAL
UNION
SELECT 1 as customer_id,'a@yahoo.com' as email,2011 as year FROM DUAL
UNION
SELECT 2 as customer_id,'b@yahoo.com' as email,2010 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@yahoo.com' as email,2012 as year FROM DUAL
UNION
SELECT 3 as customer_id,'c@google.com' as email,2012 as year FROM DUAL
),
t1 as ( SELECT year, customer_id,email,
LAG(email,1) OVER(partition by customer_id ORDER BY email) as email_prev
from t)
select year,customer_id,
sum(case when email <> email_prev or email_prev is null then 1 else 0 end ) changes
FROM t1
group by year,customer_id;
这是输出:
YEAR CUSTOMER_ID CHANGES
2010 2 1
2010 1 1
2011 1 1
2012 3 2
WITH t ( customer_id, email, year ) AS (
SELECT 1,'a@gmail.com', 2010 FROM DUAL UNION ALL
SELECT 1,'a@yahoo.com', 2011 FROM DUAL UNION ALL
SELECT 2,'b@yahoo.com', 2010 FROM DUAL UNION ALL
SELECT 3,'c@yahoo.com', 2012 FROM DUAL UNION ALL
SELECT 3,'c@google.com', 2012 FROM DUAL
)
SELECT year,
COUNT(1) AS total_changes,
COUNT( DISTINCT customer_id ) AS num_customers_changed_email
FROM (
SELECT year,
customer_id,
email,
CASE email
WHEN LAG( email, 1 ) OVER( PARTITION BY customer_id ORDER BY year )
THEN 0
ELSE 1
END as has_changed_email
FROM t
)
WHERE has_changed_email = 1
GROUP BY year
ORDER BY year;
输出:
YEAR | TOTAL_CHANGES | NUM_CUSTOMERS_CHANGED_EMAIL ---: | ------------: | --------------------------: 2010 | 2 | 2 2011 | 1 | 1 2012 | 2 | 1
db<>fiddle here