如何撰写查询以获得新捐赠者,二年级捐赠者,......?

时间:2017-09-07 14:36:04

标签: mysql

我想从每年的表格中计算新捐赠者,第二年捐赠者(连续2年),多年捐赠者(> =连续3年),失效捐赠者的数量和重新激活的捐赠者(今年再次捐赠的失效捐赠者)。我不确定这是否真的可以在一个查询中。但是,即使我必须为每个段编写单个查询,也必须有更好的方法来运行每年的查询。

为简单起见,我们假设TABLE 捐款仅包含donor_id和捐赠年度

donor_id      date_year
1             2003
1             2004
2             2003
2             2005
2             2006
2             2007
3             2005

这是我最后想知道的:

year  new_donors  second_year_donors  multi_year_donors  lapsed_donors  reactivated_donors
2003  2           0                   0                  0              0
2004  0           1                   0                  1              0
2005  1           0                   0                  1              1

我可以为新捐赠者编写查询:

SELECT d.first_year AS 'year',
       COUNT(d.id) AS 'new_donors'
  FROM (SELECT donor_id AS 'id', 
               MIN(date_year) AS 'first_year'
          FROM donations
         GROUP BY donor_id) d      
 GROUP BY year
 ORDER BY year ASC;

但是,我不知道如何写一个优雅的查询,计算所有捐赠者连续两年但不多于捐赠者。我很确定必须有比每年运行此查询更好的方法。

SELECT COUNT(DISTINCT d.donor_id) AS 'second_year_donors'
  FROM donations d
 WHERE year = 2005
   AND d.donor_id IN (
                      SELECT donor_id   
                        FROM donations 
                       WHERE year = 2004
                     )
   AND d.donor_id NOT IN (
                          SELECT donor_id
                            FROM donations
                           WHERE year = 2003
                         );

1 个答案:

答案 0 :(得分:0)

以下是一些帮助您入门的问题。我没有严格测试,但是你应该能够稍微重新调整这些,以便为new_donors和lapsed_donors提出查询:

select this.donor_year, count(*) as second_year_donors
from donations as this
join donations as prev on this.donor_year - 1 = prev.donor_year and this.donor_id = prev.donor_id
group by this.donor_year;

select this.donor_year, count(*) as third_year_donors
from donations as this
join donations as prev on this.donor_year - 1 = prev.donor_year and this.donor_id = prev.donor_id
join donations as prev2 on this.donor_year - 2 = prev2.donor_year  and this.donor_id = prev2.donor_id
group by this.donor_year;

select this.donor_year, count(distinct this.donor_id) as reactivated_donors
from donations as this
left join donations as prev on this.donor_year - 1 = prev.donor_year and this.donor_id = prev.donor_id
join donations as past on this.donor_year - 1 > past.donor_year and this.donor_id = past.donor_id
where prev.donor_id is null
group by this.donor_year;