Sql server 获取SQL中每行销售之间的平均月数

Sql server 获取SQL中每行销售之间的平均月数,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,我需要确定每行销售之间的平均月数。因此,如果我有3个空值,然后是一次销售,然后是4个空值,然后是一次销售,然后是4个空值和一次销售,我可以计算出该客户在过去24个月内购买商品的平均3.6个月4个四舍五入。因此,如果我看到从今天起5个月没有销售,我可以在该行标记该客户。customer/StockCode combo 其他样式-直接查询无轴 Name Customer StockCode Description 3/01/2013 4/01/20

我需要确定每行销售之间的平均月数。因此,如果我有3个空值,然后是一次销售,然后是4个空值,然后是一次销售,然后是4个空值和一次销售,我可以计算出该客户在过去24个月内购买商品的平均3.6个月4个四舍五入。因此,如果我看到从今天起5个月没有销售,我可以在该行标记该客户。customer/StockCode combo

其他样式-直接查询无轴

Name         Customer   StockCode       Description         3/01/2013   4/01/2013   5/01/2013   6/01/2013   7/01/2013   8/01/2013   9/01/2013   10/01/2013  11/01/2013  12/01/2013  1/01/2014   2/01/2014   3/01/2014   4/01/2014   5/01/2014   6/01/2014   7/01/2014   8/01/2014   9/01/2014   10/01/2014  11/01/2014  12/01/2014  1/01/2015   2/01/2015   3/01/2015
AAG Ice Cream   564     243702  4/1 Gal Ja-Rtu Pineapple    NULL    NULL    NULL    274.40  NULL    NULL    313.60  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    392.00  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
AAG Ice Cream   564     243701  4/1 Gal Ja-Rtu Strawberry   NULL    NULL    NULL    660.00  NULL    NULL    NULL    660.00  NULL    NULL    NULL    NULL    NULL    NULL    NULL    660.00  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
AAG Ice Cream   564     248050  4/1 Gal-RTU Choc Syrup      NULL    NULL    NULL    534.00  NULL    NULL    534.00  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    534.00  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

我所做的是创建一个GroupID字段,然后用InvoiceValue不等于0的值填充它:

CREATE TABLE [dbo].[ArSalesMove](
[Customer] [char](7) NOT NULL,
[TrnDate] [datetime] NOT NULL,
[Register] [decimal](5, 0) NOT NULL,
[SummaryLine] [decimal](5, 0) NOT NULL,
[DetailLine] [decimal](5, 0) NOT NULL,
[Invoice] [char](6) NULL,
[StockCode] [char](30) NULL,
[Warehouse] [char](2) NULL,
[InvoiceQty] [decimal](10, 3) NULL,
[InvoiceValue] [decimal](14, 2) NULL,
[CostValue] [decimal](14, 2) NULL,
[DocumentType] [char](1) NULL,
[Branch] [char](2) NULL,
[Salesperson] [char](3) NULL,
[Bin] [char](6) NULL,
[OrderType] [char](2) NULL,
[Area] [char](2) NULL,
[ProductClass] [char](4) NULL,
[TaxCode] [char](1) NULL,
[TaxValue] [decimal](14, 2) NULL,
[DiscValue] [decimal](14, 2) NULL,
[TaxCodeFst] [char](1) NULL,
[TaxValueFst] [decimal](14, 2) NULL,
[SalesOrder] [char](6) NULL,
[CustomerPoNumber] [char](30) NULL,
[TrnYear] [decimal](4, 0) NULL,
[TrnMonth] [decimal](2, 0) NULL,
[ForInvoiceValue] [decimal](14, 2) NULL,
[InvoiceCurrency] [char](3) NULL,
[SalesOrderLine] [decimal](4, 0) NULL,
[TimeStamp] [timestamp] NULL,
CONSTRAINT [ArSalesMoveKey] PRIMARY KEY CLUSTERED 
(
  [Customer] ASC,
  [TrnDate] ASC,
  [Register] ASC,
  [SummaryLine] ASC,
  [DetailLine] ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
在这里,这一切都在一个存储过程中

  CASE WHEN MonthsSinceLastSale > ZeroAvg + 1 THEN 1 ELSE 0 END as Flag -

为什么您的数据以这种方式存储?我所做的是使用数据透视创建一个临时表。解决此问题后,我将不得不考虑如何使用动态创建的列名。根据您的SQL Server版本,可能有一种更简单的方法来执行此操作,而不使用临时表和数据透视。版本为SQL 2008
CREATE TABLE [dbo].[ArSalesMove](
[Customer] [char](7) NOT NULL,
[TrnDate] [datetime] NOT NULL,
[Register] [decimal](5, 0) NOT NULL,
[SummaryLine] [decimal](5, 0) NOT NULL,
[DetailLine] [decimal](5, 0) NOT NULL,
[Invoice] [char](6) NULL,
[StockCode] [char](30) NULL,
[Warehouse] [char](2) NULL,
[InvoiceQty] [decimal](10, 3) NULL,
[InvoiceValue] [decimal](14, 2) NULL,
[CostValue] [decimal](14, 2) NULL,
[DocumentType] [char](1) NULL,
[Branch] [char](2) NULL,
[Salesperson] [char](3) NULL,
[Bin] [char](6) NULL,
[OrderType] [char](2) NULL,
[Area] [char](2) NULL,
[ProductClass] [char](4) NULL,
[TaxCode] [char](1) NULL,
[TaxValue] [decimal](14, 2) NULL,
[DiscValue] [decimal](14, 2) NULL,
[TaxCodeFst] [char](1) NULL,
[TaxValueFst] [decimal](14, 2) NULL,
[SalesOrder] [char](6) NULL,
[CustomerPoNumber] [char](30) NULL,
[TrnYear] [decimal](4, 0) NULL,
[TrnMonth] [decimal](2, 0) NULL,
[ForInvoiceValue] [decimal](14, 2) NULL,
[InvoiceCurrency] [char](3) NULL,
[SalesOrderLine] [decimal](4, 0) NULL,
[TimeStamp] [timestamp] NULL,
CONSTRAINT [ArSalesMoveKey] PRIMARY KEY CLUSTERED 
(
  [Customer] ASC,
  [TrnDate] ASC,
  [Register] ASC,
  [SummaryLine] ASC,
  [DetailLine] ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,     ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
 SET @counter = 0
 UPDATE @tempSales 
 SET @counter = tt.GroupID = @counter + 1
 FROM @tempSales  tt
 WHERE  CASE WHEN tt.InvoiceValue <> 0 THEN 1 ELSE 0 END = 1
 SELECT t1.ID,t1.TrnDate, t1.Customer,t1.StockCode,t1.InvoiceValue,
(--Fill Back null Values...
SELECT t2.GroupID
FROM @tempSales t2
WHERE t2.ID = (
    SELECT MAX(t3.ID)
    FROM @tempSales t3
    WHERE t3.ID <= t1.ID
    AND GroupID IS NOT NULL
   )
 ) AS GroupID
FROM @tempSales t1   
  CASE WHEN MonthsSinceLastSale > ZeroAvg + 1 THEN 1 ELSE 0 END as Flag -
ALTER PROC GetZeroMonthsReport
@Customer Varchar(50),
@StockCode Varchar(50)

as

DECLARE @tempSales TABLE (ID INT IDENTITY (1,1) NOT NULL PRIMARY KEY,    TrnDate DATETIME, Customer NVARCHAR(50),StockCode NVARCHAR(50), InvoiceValue      decimal, GroupID INT)
DECLARE @temp  TABLE (ID INT IDENTITY (1,1) NOT NULL PRIMARY KEY, TrnDate   DATETIME, Customer NVARCHAR(50),StockCode NVARCHAR(50), InvoiceValue decimal,   GroupID INT)
DECLARE @counter int


INSERT INTO @temp (TrnDate, Customer,StockCode, InvoiceValue)
Select  CONVERT(VARCHAR(50),MONTH(TrnDate)) + '/01/' +   CONVERT(VARCHAR(50),Year(TrnDate)) as TrnDate ,  RTRIM(Customer),RTRIM(StockCode), SUM(InvoiceValue)
FROM dbo.ArSalesMove s WITH(NOLOCK)
WHERE TrnDate BETWEEN  DATEADD(YEAR,-2,GetDate())   AND  GETDATE()
AND RTRIM(Customer)+RTRIM(StockCode) NOT IN ( SELECT   RTRIM(Customer)+RTRIM(StockCode) FROM dbo.ArSalesExclusion a WITH(NOLOCK))
 AND RTRIM(Customer)<>'999'
 AND RTRIM(StockCode)<>'704033'--Wood Pallets    
 AND RTRIM(Customer)IN (SELECT DISTINCT  RTRIM(Customer) From ArSalesMove   WHERE TrnDate Between DATEADD(YEAR,-2,GetDate())   AND  GETDATE())
 AND RTRIM(StockCode)IN (SELECT DISTINCT  RTRIM(StockCode) From ArSalesMove  WHERE TrnDate Between DATEADD(YEAR,-2,GetDate())   AND  GETDATE())
 GROUP BY Customer,StockCode,MONTH(TrnDate),Year(TrnDate)
 ORDER BY Customer,StockCode,TrnDate
;WITH enum AS 
(
Select Customer,StockCode, StartDate = CONVERT(DATETIME,    CONVERT(VARCHAR(50),MONTH(DATEADD(YEAR,-2,GetDate()) )) + '/01/' +   CONVERT(VARCHAR(50),Year(DATEADD(YEAR,-2,GetDate()) ))), --  MIN(TrnDate), 
 EndDate = GETDATE()-- MAX(TrnDate)
 FROM @temp

  Group BY Customer,StockCode 

  UNION ALL

SELECT Customer,StockCode, DATEADD(MONTH, 1, StartDate), EndDate
FROM enum 
WHERE StartDate < EndDate   
) 

INSERT INTO @tempSales (TrnDate, Customer,StockCode,InvoiceValue,GroupID)
SELECT  
e.StartDate,
e.Customer, 
e.StockCode,
InvoiceValue = ISNULL(t.InvoiceValue, 0), GroupID
FROM enum e
LEFT JOIN  @temp t ON  e.StartDate = t.TrnDate AND   e.StockCode =       t.StockCode AND e.Customer = t.Customer
ORDER BY e.Customer,e.StockCode,  e.StartDate

SET @counter = 0
UPDATE @tempSales 
SET @counter = tt.GroupID = @counter + 1
FROM @tempSales  tt
WHERE  CASE WHEN tt.InvoiceValue <> 0 THEN 1 ELSE 0 END = 1

SELECT (Select Name From ArCustomer Where RTRIM(Customer) = d.Customer) as    Name,
d.Customer,d.StockCode,
(Select [Description] From InvMaster Where RTRIM(StockCode) = d.StockCode)   as [Description],
d.LastSaleDate,d.MonthsSinceLastSale,d.ZeroAvg,d.Flag  FROM (
SELECT   c.Customer,c.StockCode,c.LastSaleDate,c.MonthsSinceLastSale,c.ZeroAvg,c.Flag 
FROM (
SELECT   b.Customer,b.StockCode,b.LastSaleDate,b.MonthsSinceLastSale,b.ZeroAvg,CASE WHEN    MonthsSinceLastSale > ZeroAvg + 1 THEN 1 ELSE 0 END as Flag --Add one month  cusion..
FROM (
SELECT a.Customer,a.StockCode,
 AVG(a.ZeroCount) as ZeroAvg,
(SELECT COUNT(TrnDate) as MonthsSinceLastSale FROM @tempSales
 WHERE Customer = a.Customer AND StockCode = a.StockCode AND  TrnDate   BETWEEN (SELECT MAX(TrnDate) FROM @tempSales tt WHERE Customer = a.Customer AND    StockCode = a.StockCode AND InvoiceValue <> 0)  AND GETDATE()) as   MonthsSinceLastSale,
 (SELECT MAX(TrnDate) FROM @tempSales tt WHERE Customer = a.Customer AND    StockCode = a.StockCode AND  InvoiceValue<> 0) as LastSaleDate
 FROM (
 Select COUNT(z.GroupID) as ZeroCount,z.Customer,z.StockCode,z.GroupID 
 FROM (

 SELECT  x.ID,x.TrnDate,    x.Customer,x.StockCode,x.InvoiceValue,ISNULL(x.GroupID,0) as GroupID
 FROM (
 SELECT t1.ID,t1.TrnDate, t1.Customer,t1.StockCode,t1.InvoiceValue,
 (--Fill Back null Values...
  SELECT t2.GroupID
  FROM @tempSales t2
  WHERE t2.ID = (
    SELECT MAX(t3.ID)
    FROM @tempSales t3
    WHERE t3.ID <= t1.ID
    AND GroupID IS NOT NULL
   )
  ) AS GroupID
 FROM @tempSales t1
 ) as x
 ) as z

 WHERE z.InvoiceValue = 0
 GROUP BY z.GroupID,z.Customer,z.StockCode
  ) as a
  GROUP BY  Customer,StockCode
  ) as b
  WHERE b.LastSaleDate IS NOT NULL
  ) as c
  Where c.Flag = 1
  ) as d 
 ORDER BY d.Customer,d.StockCode