Sql 按财政年度分组并将这些组作为筛选器应用

Sql 按财政年度分组并将这些组作为筛选器应用,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我希望建立6个组,客户可分为: 非购买者从未从我们这里购买 本财政年度内首次购买的新购买者 在当前财政年度以及最近第二个财政年度购买的重新激活的买方 在上一财年购买的失效买方,但不是当前财年 连续2年的购买者在当前财政年度和最近一个财政年度购买 在过去3或4个财政年度,连续3-4年的购买者每年购买 连续5年以上的购买者在每个财政年度购买至少5年 我将使用的财政年度为4月1日至3月31日,并将使用以下表格: purchaser (including id (primary key)) purch

我希望建立6个组,客户可分为:

非购买者从未从我们这里购买 本财政年度内首次购买的新购买者 在当前财政年度以及最近第二个财政年度购买的重新激活的买方 在上一财年购买的失效买方,但不是当前财年 连续2年的购买者在当前财政年度和最近一个财政年度购买 在过去3或4个财政年度,连续3-4年的购买者每年购买 连续5年以上的购买者在每个财政年度购买至少5年

我将使用的财政年度为4月1日至3月31日,并将使用以下表格:

purchaser (including id (primary key))

purchases (date_purchased, purchases_purchaser_id)
其中,各表在买方id=买方id上连接,每个买方可以在任何财政年度内进行多次采购,因此也可以按年度进行分组

这让我抓狂,所以我非常感谢你的帮助

谢谢,
Davin

虽然使用另一个显示5个会计年度的日期范围表可以更轻松一些,但我已经为您的查询硬编码了起始/截止日期参考,并且似乎正在工作

内部选择将根据给定日期范围内的任何一次或多次购买预收集标志。。。例如:2010年4月1日=20100401,日期转换为2011年3月31日=20110331,并循环过去5年。。。此外,在“实际购买”表中有一个标记,用于统计任何购买日期,以确认从未购买过的与购买6、7年或更久历史的人

该查询的基础将基本上创建一个可能发生活动的各个年份的交叉表。然后,我可以用最详细的条件查询它们分类的某些标题,直到最不

我尽可能地从另一种SQL语言转换,以遵守SQL Server语法,主要是关于日期转换,但除此之外,原则和查询确实有效。。。最后一个分类列是character,但可以是您想要替代的任何列

SELECT
      id,
      CASE 
         WHEN year1 + year2 + year3 + year4 + year5 = 5 THEN "5+yrs "
         WHEN year1 + year2 + year3 + year4 >= 3 THEN "3-4yrs"
         WHEN year1 + year2 = 2, "2yrs  "
         WHEN year1 = 1 AND year2 = 0 AND year3 = 1 THEN "Reacti"
         WHEN year1 = 1 THEN "New   "
         WHEN year1 = 0 AND year2 = 1 THEN "Lapsed"
         WHEN AnyPurchase = 1, "over5"
         ELSE "never" BuyerClassification
      END
   FROM
      ( SELECT
            id,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20100401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20110331", 112 ) 
                 THEN 1 ELSE 0 END ) Year1,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20090401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20100331", 112 )
                 THEN 1 ELSE 0 END ) Year2,
            MAX( CASE WEHEN date_purchased >= CONVERT( Date, "20080401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20090331", 112 )
                 THEN 1 ELSE 0 END ) Year3,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20070401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20080331", 112 )
                 THEN 1 ELSE 0 END ) Year4,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20060401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20070331", 112 )
                 THEN 1 ELSE 0 END ) Year5,
            MAX( CASE WHEN date_purchased <= CONVERT( Date, "20100401", 112 )
                 THEN 1 ELSE 0 END ) AnyPurchase
         FROM
            purchaser LEFT OUTER JOIN purchases
               ON purchaser.id = purchases.purchases_purchaser_id
         GROUP BY 
            1 ) PreGroup1
编辑- 通过语法转换修复了parens,但没有修复它

Group By 1是指根据查询中的第一列进行分组,该列是来自买方的买方ID。通过执行左外联接,将保证购买者表中所有可能的人,而不管实际购买了什么。PreGroup1是select语句的别名,以防您想在最外层的select语句中执行其他连接,在该语句中检测分类的年份值


虽然它可以工作,但可能没有其他人通过分析查询而插话的效率高,但它可能会让您对一些查询和聚合技术有所了解。这个过程基本上是通过使用内部SQL Select上的case/when构造和最外部SQL Select中的最终分类来创建一种交叉表。

尽管使用另一个显示5个会计年度的日期范围表可以更容易地完成,我已经为您的查询硬编码了起始/截止日期的参考资料,似乎正在工作

内部选择将根据给定日期范围内的任何一次或多次购买预收集标志。。。例如:2010年4月1日=20100401,日期转换为2011年3月31日=20110331,并循环过去5年。。。此外,在“实际购买”表中有一个标记,用于统计任何购买日期,以确认从未购买过的与购买6、7年或更久历史的人

该查询的基础将基本上创建一个可能发生活动的各个年份的交叉表。然后,我可以用最详细的条件查询它们分类的某些标题,直到最不

我尽可能地从另一种SQL语言转换,以遵守SQL Server语法,主要是关于日期转换,但除此之外,原则和查询确实有效。。。最后一个分类列是character,但可以是您想要替代的任何列

SELECT
      id,
      CASE 
         WHEN year1 + year2 + year3 + year4 + year5 = 5 THEN "5+yrs "
         WHEN year1 + year2 + year3 + year4 >= 3 THEN "3-4yrs"
         WHEN year1 + year2 = 2, "2yrs  "
         WHEN year1 = 1 AND year2 = 0 AND year3 = 1 THEN "Reacti"
         WHEN year1 = 1 THEN "New   "
         WHEN year1 = 0 AND year2 = 1 THEN "Lapsed"
         WHEN AnyPurchase = 1, "over5"
         ELSE "never" BuyerClassification
      END
   FROM
      ( SELECT
            id,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20100401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20110331", 112 ) 
                 THEN 1 ELSE 0 END ) Year1,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20090401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20100331", 112 )
                 THEN 1 ELSE 0 END ) Year2,
            MAX( CASE WEHEN date_purchased >= CONVERT( Date, "20080401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20090331", 112 )
                 THEN 1 ELSE 0 END ) Year3,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20070401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20080331", 112 )
                 THEN 1 ELSE 0 END ) Year4,
            MAX( CASE WHEN date_purchased >= CONVERT( Date, "20060401", 112 ) 
                       AND date_purchased <= CONVERT( Date, "20070331", 112 )
                 THEN 1 ELSE 0 END ) Year5,
            MAX( CASE WHEN date_purchased <= CONVERT( Date, "20100401", 112 )
                 THEN 1 ELSE 0 END ) AnyPurchase
         FROM
            purchaser LEFT OUTER JOIN purchases
               ON purchaser.id = purchases.purchases_purchaser_id
         GROUP BY 
            1 ) PreGroup1
编辑- 通过语法转换修复了parens,但没有修复它

Group By 1是指根据查询中的第一列进行分组,该列是来自买方的买方ID。通过执行左外联接,将保证购买者表中所有可能的人,而不管实际购买了什么。PreGroup1是select语句的别名,以防您想在最外层的select语句中执行其他连接,在该语句中检测分类的年份值

虽然它可以工作,但可能没有其他人通过分析查询而插话的效率高,但它可能会让您对一些查询和聚合技术有所了解。这个过程基本上是通过利用内部sqlselect上的case/when构造和f
最外层SQL Select中的最终分类。

MS SQL Server在2000年、2005年和2008年工作

SET NOCOUNT ON

CREATE TABLE #purchasers (purchaser_id int, pName varchar(20))

Insert Into #purchasers values (0, 'Non-purchaser')
Insert Into #purchasers values (1, 'New purchaser')
Insert Into #purchasers values (2, 'Reactivated')
Insert Into #purchasers values (3, 'Lapsed')
Insert Into #purchasers values (4, '2 yr Consecutive')
Insert Into #purchasers values (5, '3 yr consecutive')
Insert Into #purchasers values (6, '4 yr consecutive')
Insert Into #purchasers values (7, '5+ year consecutive')
Insert Into #purchasers values (8, 'Uncategorized')
Insert Into #purchasers values (9, 'old one')


CREATE TABLE #purchases (date_purchased datetime, purchases_purchaser_id int)

Insert Into #purchases values ('2010/05/03', 1)

Insert Into #purchases values ('2007/05/03', 2)
Insert Into #purchases values ('2008/05/03', 2)
Insert Into #purchases values ('2010/05/03', 2)

Insert Into #purchases values ('2008/05/03', 3)
Insert Into #purchases values ('2009/05/03', 3)


Insert Into #purchases values ('2009/05/03', 4)
Insert Into #purchases values ('2010/05/03', 4)

Insert Into #purchases values ('2008/05/03', 5)
Insert Into #purchases values ('2009/05/03', 5)
Insert Into #purchases values ('2010/05/03', 5)

Insert Into #purchases values ('2007/05/03', 6)
Insert Into #purchases values ('2008/05/03', 6)
Insert Into #purchases values ('2009/05/03', 6)
Insert Into #purchases values ('2010/05/03', 6)

Insert Into #purchases values ('2004/05/03', 7)
Insert Into #purchases values ('2005/05/03', 7)
Insert Into #purchases values ('2006/05/03', 7)
Insert Into #purchases values ('2007/05/03', 7)
Insert Into #purchases values ('2008/05/03', 7)
Insert Into #purchases values ('2009/05/03', 7)
Insert Into #purchases values ('2009/05/03', 7)
Insert Into #purchases values ('2009/05/03', 7)
Insert Into #purchases values ('2010/05/03', 7)

Insert Into #purchases values ('2007/05/03', 8)

Insert Into #purchases values ('2000/05/03', 9)

Select p.pName,
       p.purchaser_id,
       isNull(a.[2005],0) as [Bef.2006],
       isNull(a.[2006],0) as [2006],
       isNull(a.[2007],0) as [2007],
       isNull(a.[2008],0) as [2008],
       isNull(a.[2009],0) as [2009],
       isNull(a.[2010],0) as [2010],
       isNull(a.Category, 'Non-purchaser') as Category
From #purchasers p
Left Join 
(        
   Select purchases_purchaser_id, [2005],[2006],[2007],[2008],[2009],[2010],
         Case When [2006]+[2007]+[2008]+[2009]+[2010] = 5 Then '5+ year consecutive'
              When [2008]+[2009]+[2010] = 3               Then '3-4 yr consecutive'
              When [2009]+[2010] = 2                      Then '2 yr Consecutive'
              When [2009]=1 and [2010]=0                  Then 'Lapsed'
              When [2008]=1 and [2009]=0 and [2010]=1     Then 'Reactivated'
              When [2006]+[2007]+[2008]+[2009]=0 and [2010]=1 Then 'New'
              When [2006]+[2007]+[2008]+[2009]+[2010] = 0 Then 'Non-purchaser in last 5 yrs'
              Else 'non categorized'
         End as Category     
   From (
            Select purchases_purchaser_id, 
                   Case When date_purchased < '2006/04/01' Then 2005 
                        Else Year(date_purchased)- Case When month(date_purchased)<4 Then -1 else 0 end 
                     end as fiscalYear, count(*) as nPurchases
            From #purchases 
            Group by purchases_purchaser_id,
                     Case When date_purchased < '2006/04/01' Then 2005 
                        Else Year(date_purchased)- Case When month(date_purchased)<4 Then -1 else 0 end 
                     end
         ) as AggData
   PIVOT ( count(nPurchases) for fiscalYear in ([2005],[2006],[2007],[2008],[2009],[2010]) ) pvt
) as a
on p.purchaser_id=a.purchases_purchaser_id

MS SQL Server在2000年、2005年和2008年工作

SET NOCOUNT ON

CREATE TABLE #purchasers (purchaser_id int, pName varchar(20))

Insert Into #purchasers values (0, 'Non-purchaser')
Insert Into #purchasers values (1, 'New purchaser')
Insert Into #purchasers values (2, 'Reactivated')
Insert Into #purchasers values (3, 'Lapsed')
Insert Into #purchasers values (4, '2 yr Consecutive')
Insert Into #purchasers values (5, '3 yr consecutive')
Insert Into #purchasers values (6, '4 yr consecutive')
Insert Into #purchasers values (7, '5+ year consecutive')
Insert Into #purchasers values (8, 'Uncategorized')
Insert Into #purchasers values (9, 'old one')


CREATE TABLE #purchases (date_purchased datetime, purchases_purchaser_id int)

Insert Into #purchases values ('2010/05/03', 1)

Insert Into #purchases values ('2007/05/03', 2)
Insert Into #purchases values ('2008/05/03', 2)
Insert Into #purchases values ('2010/05/03', 2)

Insert Into #purchases values ('2008/05/03', 3)
Insert Into #purchases values ('2009/05/03', 3)


Insert Into #purchases values ('2009/05/03', 4)
Insert Into #purchases values ('2010/05/03', 4)

Insert Into #purchases values ('2008/05/03', 5)
Insert Into #purchases values ('2009/05/03', 5)
Insert Into #purchases values ('2010/05/03', 5)

Insert Into #purchases values ('2007/05/03', 6)
Insert Into #purchases values ('2008/05/03', 6)
Insert Into #purchases values ('2009/05/03', 6)
Insert Into #purchases values ('2010/05/03', 6)

Insert Into #purchases values ('2004/05/03', 7)
Insert Into #purchases values ('2005/05/03', 7)
Insert Into #purchases values ('2006/05/03', 7)
Insert Into #purchases values ('2007/05/03', 7)
Insert Into #purchases values ('2008/05/03', 7)
Insert Into #purchases values ('2009/05/03', 7)
Insert Into #purchases values ('2009/05/03', 7)
Insert Into #purchases values ('2009/05/03', 7)
Insert Into #purchases values ('2010/05/03', 7)

Insert Into #purchases values ('2007/05/03', 8)

Insert Into #purchases values ('2000/05/03', 9)

Select p.pName,
       p.purchaser_id,
       isNull(a.[2005],0) as [Bef.2006],
       isNull(a.[2006],0) as [2006],
       isNull(a.[2007],0) as [2007],
       isNull(a.[2008],0) as [2008],
       isNull(a.[2009],0) as [2009],
       isNull(a.[2010],0) as [2010],
       isNull(a.Category, 'Non-purchaser') as Category
From #purchasers p
Left Join 
(        
   Select purchases_purchaser_id, [2005],[2006],[2007],[2008],[2009],[2010],
         Case When [2006]+[2007]+[2008]+[2009]+[2010] = 5 Then '5+ year consecutive'
              When [2008]+[2009]+[2010] = 3               Then '3-4 yr consecutive'
              When [2009]+[2010] = 2                      Then '2 yr Consecutive'
              When [2009]=1 and [2010]=0                  Then 'Lapsed'
              When [2008]=1 and [2009]=0 and [2010]=1     Then 'Reactivated'
              When [2006]+[2007]+[2008]+[2009]=0 and [2010]=1 Then 'New'
              When [2006]+[2007]+[2008]+[2009]+[2010] = 0 Then 'Non-purchaser in last 5 yrs'
              Else 'non categorized'
         End as Category     
   From (
            Select purchases_purchaser_id, 
                   Case When date_purchased < '2006/04/01' Then 2005 
                        Else Year(date_purchased)- Case When month(date_purchased)<4 Then -1 else 0 end 
                     end as fiscalYear, count(*) as nPurchases
            From #purchases 
            Group by purchases_purchaser_id,
                     Case When date_purchased < '2006/04/01' Then 2005 
                        Else Year(date_purchased)- Case When month(date_purchased)<4 Then -1 else 0 end 
                     end
         ) as AggData
   PIVOT ( count(nPurchases) for fiscalYear in ([2005],[2006],[2007],[2008],[2009],[2010]) ) pvt
) as a
on p.purchaser_id=a.purchases_purchaser_id

这里是动态版本

Declare @currentYear int
Declare @OlderThan5yrs datetime 

Set @currentYear  = Year(GetDate()) - Case When month(GetDate())<4 then 1 else 0 end
Set @OlderThan5yrs = cast(cast( @currentYear-5 as varchar(4))+'/04/01' as datetime)

Select p.pName,
       p.purchaser_id,
       isNull(a.[5+YrAgo],0) as [5+YrAgo],
       isNull(a.[4YrAgo], 0)  as [4YrAgo],
       isNull(a.[3YrAgo], 0)  as [3YrAgo],
       isNull(a.[2YrAgo], 0)  as [2YrAgo],
       isNull(a.[1YrAgo], 0)  as [1YrAgo],
       isNull(a.[CurYr],  0)   as [CurYr],
       isNull(a.Category, 'Non-purchaser (ever)') as Category
From purchasers p
Left Join 
(        
   Select purchases_purchaser_id, 
          [5] as [5+YrAgo],
          [4] as [4YrAgo],
          [3] as [3YrAgo],
          [2] as [2YrAgo],
          [1] as [1YrAgo],
          [0]  as [CurYr],
         Case When [4]+[3]+[2]+[1]+[0] = 5     Then '5+ year consecutive'
              When [2]+[1]+[0] = 3             Then '3-4 yr consecutive'
              When [1]+[0] = 2                 Then '2 yr Consecutive'
              When [1]=1 and [0]=0             Then 'Lapsed'
              When [2]=1 and [1]=0 and [0]=1   Then 'Reactivated'
              When [4]+[3]+[2]+[1]=0 and [0]=1 Then 'New'
              When [4]+[3]+[2]+[1]+[0] = 0     Then 'Non-purchaser (last 5 yrs)'
              Else 'non categorized'
         End as Category     
   From (
            Select purchases_purchaser_id, 
                   Case When date_purchased < @OlderThan5yrs Then 5 
                        Else @currentYear - Year(date_purchased)+ Case When month(date_purchased)<4 Then 1 else 0 end 
                     end as fiscalYear, count(*) as nPurchases
            From purchases 
            Group by purchases_purchaser_id,
                   Case When date_purchased < @OlderThan5yrs Then 5 
                        Else @currentYear - Year(date_purchased)+ Case When month(date_purchased)<4 Then 1 else 0 end 
                     end
         ) as AggData
   PIVOT ( count(nPurchases) for fiscalYear in ([5],[4],[3],[2],[1],[0]) ) pvt
) as a
on p.purchaser_id=a.purchases_purchaser_id
您也不需要列[5+YrAgo]、[4YrAgo]、[3YrAgo]、[2YrAgo]、[1YrAgo]和[CurYr]。 我添加它们是为了更容易检查查询逻辑

更新2

以下是您在评论中提出的问题。 笔记 我在查询中使用的表结构是:

Table purchasers ( purchaser_id int, pName varchar(20))
Table purchases (purchases_purchaser_id int, date_purchased datetime)
并且在采购商id上有一个外键引用采购商id

;With AggData as (
Select   purchases_purchaser_id, 
         Case When [4]+[3]+[2]+[1]+[0] = 5     Then 1 end as [Consec5],
         Case When [4]=0 and [2]+[1]+[0] = 3   Then 1 end as [Consec34],
         Case When [2]=0 and [1]+[0] = 2       Then 1 end as [Consec2],
         Case When [1]=1 and [0]=0             Then 1 end as [Lapsed],
         Case When [2]=1 and [1]=0 and [0]=1   Then 1 end as [Reactivated],
         Case When [4]+[3]+[2]+[1]=0 and [0]=1 Then 1 end as [New],
         Case When [4]+[3]+[2]>0 and [1]+[0]=0 Then 1 end as [Uncateg]
   From  (
            Select purchases_purchaser_id, 
                   @currentYear - Year(date_purchased) + Case When month(date_purchased)<4 Then 1 else 0 end as fiscalYear, 
                   count(*) as nPurchases
              From purchases      
             Where date_purchased >= @OlderThan5yrs  
             Group by purchases_purchaser_id,
                      @currentYear - Year(date_purchased) + Case When month(date_purchased)<4 Then 1 else 0 end
         ) as AggData
   PIVOT ( count(nPurchases) for fiscalYear in ([4],[3],[2],[1],[0]) ) pvt
)
Select count([Consec5])     as [Consec5],
       count([Consec34])    as [Consec34],
       count([Consec2])     as [Consec2],
       count([Lapsed])      as [Lapsed],
       count([Reactivated]) as [Reactivated],
       count([New])         as [New],
       count(*)-count(a.purchases_purchaser_id) as [Non],
       count([Uncateg])     as [Uncateg]
  From purchasers p
 Left Join AggData as a
  on p.purchaser_id=a.purchases_purchaser_id              

这里是动态版本

Declare @currentYear int
Declare @OlderThan5yrs datetime 

Set @currentYear  = Year(GetDate()) - Case When month(GetDate())<4 then 1 else 0 end
Set @OlderThan5yrs = cast(cast( @currentYear-5 as varchar(4))+'/04/01' as datetime)

Select p.pName,
       p.purchaser_id,
       isNull(a.[5+YrAgo],0) as [5+YrAgo],
       isNull(a.[4YrAgo], 0)  as [4YrAgo],
       isNull(a.[3YrAgo], 0)  as [3YrAgo],
       isNull(a.[2YrAgo], 0)  as [2YrAgo],
       isNull(a.[1YrAgo], 0)  as [1YrAgo],
       isNull(a.[CurYr],  0)   as [CurYr],
       isNull(a.Category, 'Non-purchaser (ever)') as Category
From purchasers p
Left Join 
(        
   Select purchases_purchaser_id, 
          [5] as [5+YrAgo],
          [4] as [4YrAgo],
          [3] as [3YrAgo],
          [2] as [2YrAgo],
          [1] as [1YrAgo],
          [0]  as [CurYr],
         Case When [4]+[3]+[2]+[1]+[0] = 5     Then '5+ year consecutive'
              When [2]+[1]+[0] = 3             Then '3-4 yr consecutive'
              When [1]+[0] = 2                 Then '2 yr Consecutive'
              When [1]=1 and [0]=0             Then 'Lapsed'
              When [2]=1 and [1]=0 and [0]=1   Then 'Reactivated'
              When [4]+[3]+[2]+[1]=0 and [0]=1 Then 'New'
              When [4]+[3]+[2]+[1]+[0] = 0     Then 'Non-purchaser (last 5 yrs)'
              Else 'non categorized'
         End as Category     
   From (
            Select purchases_purchaser_id, 
                   Case When date_purchased < @OlderThan5yrs Then 5 
                        Else @currentYear - Year(date_purchased)+ Case When month(date_purchased)<4 Then 1 else 0 end 
                     end as fiscalYear, count(*) as nPurchases
            From purchases 
            Group by purchases_purchaser_id,
                   Case When date_purchased < @OlderThan5yrs Then 5 
                        Else @currentYear - Year(date_purchased)+ Case When month(date_purchased)<4 Then 1 else 0 end 
                     end
         ) as AggData
   PIVOT ( count(nPurchases) for fiscalYear in ([5],[4],[3],[2],[1],[0]) ) pvt
) as a
on p.purchaser_id=a.purchases_purchaser_id
您也不需要列[5+YrAgo]、[4YrAgo]、[3YrAgo]、[2YrAgo]、[1YrAgo]和[CurYr]。 我添加它们是为了更容易检查查询逻辑

更新2

以下是您在评论中提出的问题。 笔记 我在查询中使用的表结构是:

Table purchasers ( purchaser_id int, pName varchar(20))
Table purchases (purchases_purchaser_id int, date_purchased datetime)
并且在采购商id上有一个外键引用采购商id

;With AggData as (
Select   purchases_purchaser_id, 
         Case When [4]+[3]+[2]+[1]+[0] = 5     Then 1 end as [Consec5],
         Case When [4]=0 and [2]+[1]+[0] = 3   Then 1 end as [Consec34],
         Case When [2]=0 and [1]+[0] = 2       Then 1 end as [Consec2],
         Case When [1]=1 and [0]=0             Then 1 end as [Lapsed],
         Case When [2]=1 and [1]=0 and [0]=1   Then 1 end as [Reactivated],
         Case When [4]+[3]+[2]+[1]=0 and [0]=1 Then 1 end as [New],
         Case When [4]+[3]+[2]>0 and [1]+[0]=0 Then 1 end as [Uncateg]
   From  (
            Select purchases_purchaser_id, 
                   @currentYear - Year(date_purchased) + Case When month(date_purchased)<4 Then 1 else 0 end as fiscalYear, 
                   count(*) as nPurchases
              From purchases      
             Where date_purchased >= @OlderThan5yrs  
             Group by purchases_purchaser_id,
                      @currentYear - Year(date_purchased) + Case When month(date_purchased)<4 Then 1 else 0 end
         ) as AggData
   PIVOT ( count(nPurchases) for fiscalYear in ([4],[3],[2],[1],[0]) ) pvt
)
Select count([Consec5])     as [Consec5],
       count([Consec34])    as [Consec34],
       count([Consec2])     as [Consec2],
       count([Lapsed])      as [Lapsed],
       count([Reactivated]) as [Reactivated],
       count([New])         as [New],
       count(*)-count(a.purchases_purchaser_id) as [Non],
       count([Uncateg])     as [Uncateg]
  From purchasers p
 Left Join AggData as a
  on p.purchaser_id=a.purchases_purchaser_id              

你的SQL Server版本是什么?我正在使用2005年你的SQL Server版本是什么?我正在使用2005年谢谢,看起来棒极了!对不起,这个问题太愚蠢了,但是分组前1组指的是什么?该组是否应改为使用purchaser.id?也可以将日期设置为滚动5年,而不是硬编码,例如:SET@year=CONVERTNVARCHAR7,YEARGETDATE SET@pyear=CONVERTNVARCHAR7,YEARGETDATE-1将@yr_start=CAST'01/04/'+@pyear设置为DATETIME集@yr_end=CAST'31/03/'+@year设置为DATETIME,因为我是SQL新手,不确定这是否毫无意义!再次非常感谢,Davin:-您的For BuyerClassification条件必须修改,但没有反映初始条件-您的方法对purchases表执行10次表扫描,如果您有大量行,这是无效的-语法不正确:缺少一些THEN子句,别名BuyerClassification应位于END子句之后,不是之前,Max应该在末尾和列别名之间有右括号。时间/IO比较1000000行在purchases:DRApp表“purchases”中。扫描计数10,逻辑读取5774。。。表“购买者”。扫描计数1,逻辑读取2。。。CPU时间=1669毫秒,运行时间=1678毫秒。Niikola:表“工作台”。扫描计数0,逻辑读取0。。。表“采购”。扫描计数1,逻辑读取2598。。。表“购买者”。扫描计数1,逻辑读取2。。。CPU时间=827毫秒,运行时间=798毫秒。谢谢,看起来棒极了!对不起,这个问题太愚蠢了,但是分组前1组指的是什么?该组是否应改为使用purchaser.id?也可以将日期设置为滚动5年,而不是硬编码,例如:SET@year=CONVERTNVARCHAR7,YEARGETDATE SET@pyear=CONVERTNVARCHAR7,YEARGETDATE-1将@yr_start=CAST'01/04/'+@pyear设置为DATETIME集@yr_end=CAST'31/03/'+@year设置为DATETIME,因为我是SQL新手,不确定这是否毫无意义!再次非常感谢,Davin:-您的For BuyerClassification条件必须修改,但没有反映初始条件-您的方法对purchases表执行10次表扫描,如果您有大量行,这是无效的-语法不正确:缺少一些THEN子句,别名BuyerClassification应位于END子句之后,不是之前,Max应该在末尾和列别名之间有右括号。时间/IO比较1000000行在purchases:DRApp表“purchases”中。扫描计数10,逻辑读取5774。。。表“购买者”。扫描计数1,逻辑读取2。。。CPU时间=1669毫秒,运行时间=1678毫秒。Niikola:表“工作台”。扫描计数0,逻辑读取0。。。表“采购”。扫描计数1,逻辑读取2598。。。表“购买者”。扫描计数1,逻辑读取2。。。CPU时间=827毫秒,运行时间=798毫秒。非常感谢:我担心我有点搞不清楚我到底是如何实现这一点的,因为提取的数据都是指预填充的临时表?将其重定向到实际数据源时,是否不需要实际创建临时表?对不起,如果这是一个愚蠢的问题!这些临时表只是模拟您的数据。您应该用真实的表名更改表名。我创建这些表和填充数据只是为了使测试更容易——您可以复制整个代码并执行它,以查看查询是否返回您期望的结果。顺便说一句,有些情况没有涵盖,我将它们标记为未分类。过去5年中从未购买和未购买的购买者之间也存在差异。如果您只想覆盖当前和前4年,而忽略之前的所有内容,则可以使查询速度更快,在“从购买:何处购买日期>=”2006/04/01“之后添加WHERE子句。对于下面的查询,它将是购买日期>=@OlderThan5yrs。在这两个查询中,您都可以删除列[2005]和[5]。非常感谢这一点:我恐怕有点困惑,我实际上是如何实现这一点的,因为数据pul
led all是指已预填充的临时表?将其重定向到实际数据源时,是否不需要实际创建临时表?对不起,如果这是一个愚蠢的问题!这些临时表只是模拟您的数据。您应该用真实的表名更改表名。我创建这些表和填充数据只是为了使测试更容易——您可以复制整个代码并执行它,以查看查询是否返回您期望的结果。顺便说一句,有些情况没有涵盖,我将它们标记为未分类。过去5年中从未购买和未购买的购买者之间也存在差异。如果您只想覆盖当前和前4年,而忽略之前的所有内容,则可以使查询速度更快,在“从购买:何处购买日期>=”2006/04/01“之后添加WHERE子句。对于下面的查询,它将是购买日期>=@OlderThan5yrs。在这两个查询中,您都可以删除列[2005]和[5]。哇!再次感谢您在我之前回复您查询的动态版本之前没有看到它,它会出现一条错误消息“无效对象名称”purchaser还请您澄清为什么p.purchaser\u id=a.purchases\u purchaser\u id结尾不是:p.purchaser\u id=a.purchases.purchaser\u id?因为“购买”是一个完全独立的表?如果您给采购表一个类似ps的别名,它会抛出错误吗?正如我在上面所问的,如果您能澄清p.pName如何适合我之前存在的数据库,那将是非常棒的:正如我前面所说的,您必须修改表名和列名以适合您的模式。如果在purchases表中purchaser id列名是相同的purchaser\u id,则只需将所有purchases\u purchaser\u id替换为purchaser\u id a.purchases\u purchaser\u id将是a.purchaser\u id.pName,我添加该名称只是为了更容易检查我们是否获得了所需的数据,我插入了与purchaser name匹配的数据:-。如果有,您可以使用“采购商名称”列,也可以从“选择”中删除该列。抱歉,继续提问,但我将如何计算每个pName的总计,即,不是为每个客户单独计算一行,而是总共只有九行,每个pName类别1行-如我所示;我不习惯旋转,我不确定我需要在哪里添加计数函数!!再一次,非常感谢,这是一个真正的救命恩人:我用总数更新了帖子。顺便说一句,pName是购买者的名字,而不是类别——我只是把名字放在与预期类别相同的地方,但在现实生活中它必须是个人/公司的名字,它在购买者表中。哇!再次感谢您在我之前回复您查询的动态版本之前没有看到它,它会出现一条错误消息“无效对象名称”purchaser还请您澄清为什么p.purchaser\u id=a.purchases\u purchaser\u id结尾不是:p.purchaser\u id=a.purchases.purchaser\u id?因为“购买”是一个完全独立的表?如果您给采购表一个类似ps的别名,它会抛出错误吗?正如我在上面所问的,如果您能澄清p.pName如何适合我之前存在的数据库,那将是非常棒的:正如我前面所说的,您必须修改表名和列名以适合您的模式。如果在purchases表中purchaser id列名是相同的purchaser\u id,则只需将所有purchases\u purchaser\u id替换为purchaser\u id a.purchases\u purchaser\u id将是a.purchaser\u id.pName,我添加该名称只是为了更容易检查我们是否获得了所需的数据,我插入了与purchaser name匹配的数据:-。如果有,您可以使用“采购商名称”列,也可以从“选择”中删除该列。抱歉,继续提问,但我将如何计算每个pName的总计,即,不是为每个客户单独计算一行,而是总共只有九行,每个pName类别1行-如我所示;我不习惯旋转,我不确定我需要在哪里添加计数函数!!再一次,非常感谢,这是一个真正的救命恩人:我用总数更新了帖子。顺便说一句,pName是购买者的名字,而不是类别——我只是把名字和预期的类别放在一起,但在现实生活中它必须是个人/公司的名字,它在购买者表中。