使用分析函数计算变化数

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