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