SQL中的LFL销售查询

时间:2009-07-16 15:00:30

标签: sql sql-server database

这可能看起来有点像我的作业问题(而且确实如此),但我认为我想要获得的销售结果相当通用,对任何进行销售的人都有用报告。

我在SQL Server 2005中有一个基本的销售表(字段:分支 DateOfSale SalesAmount )我需要使用该表中的数据构建一个报告。我正在使用SQL,它将为我提供该报告的数据。

实际的表使用了BranchID,在本例中我将其更改为Branch。

设置脚本

-- create sales table
CREATE TABLE Sales(
Branch varchar(30) NOT NULL,
DateOfSale smalldatetime NOT NULL,
SalesAmount money NOT NULL)

-- London: same week last year
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090714',100)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090715',200)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090716',300)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090717',400)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090718',500)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090719',600)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090720',700)

-- London: last 2 weeks sales
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090706',1000)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090707',1100)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090708',1200)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090709',1300)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090710',1400)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090711',1500)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090712',1600)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090713',1700)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090714',1800)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('London','20090715',1900)

-- Cape Town: last 2 weeks sales
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090706',2000)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090707',2100)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090708',2200)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090709',2300)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090710',2400)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090711',2500)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090712',2600)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090713',2700)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090714',2800)
INSERT INTO Sales (Branch, DateOfSale, SalesAmount) VALUES ('Cape Town','20090715',2900)

假设

  1. 一周的第一天是星期一
  2. 今天的日期是2009年7月16日星期三
  3. 必填结果

    Branch   DailySales   DailyLFL    WTD         WTDLFL     LFL
    London       1900.00    300.00      5400.00     600.00       Y
    Cape Town    2900.00    2200.00     8400.00     6300.00
    

    每日销售 昨天的销售

    DailyLFL :类似销售。那么,1年前这一天的销售情况。不是在7月15日的这一天,而是在第29周的星期三(即7月16日)。如果这个分支不到一年(如开普敦分行),那么使用上周销售(即上周三周)。如果上周没有销售,则为零。

    WTD :本周至今。销售额从本周一开始累计至昨天。所以,Mon,Tues,Wed在我的例子中。

    WTD LFL : 每周都是喜欢的。与LFL相同的逻辑,但这次使用WTD而不是每日销售

    LFL : 有点标志显示我们是否能够使用LFL(值:1)或必须使用上周的销售额(值:0)

    由于这些是零售业的标准指标,我希望有人已经为他们编写了SQL。也许不是你最近一年没有使用的最后一周,但绝对是LFL和WTD。

    如果解决方案需要日历表(例如http://tinyurl.com/nt5gck),那很好。

1 个答案:

答案 0 :(得分:1)

我得不到好的答案,所以我必须自己做。为了完整起见,这是我的答案。

请注意,答案使用我的数据库中的真实表名(Sales_ByDay:ProfitCentreID,DateOfSale,NetSalesAmt),而不是我在问题中引用的虚构表(Sales:Branch,DateOfSale,SalesAmount)

功能:Alerts_DailySales

create function Alerts_DailySales
(
@StartDate smalldatetime, 
@EndDate smalldatetime
)
returns table
as
return
(
select 
r.ProfitCentreID, 
s.DateOfSale, 
sum(s.NetSalesAmt) DailySales
from Sales_ByDay s
inner join RevenueCentres r on s.RevenueCentreID = r.RevenueCentreID
where s.DateOfSale >= @StartDate
and s.DateOfSale <= @EndDate
group by r.ProfitCentreID, s.DateOfSale
)

功能:Alerts_WTDSales

create function Alerts_WTDSales
(
@StartDate smalldatetime, 
@EndDate smalldatetime
)
returns table
as
return
(
select
a.ProfitCentreID,
a.DateOfSale, 
max(a.DailySales) DailySales, 
sum (b.DailySales) WTDSales
from dbo.Alerts_DailySales(@StartDate, @EndDate) a
left outer join dbo.Alerts_DailySales(@StartDate, @EndDate) b on a.ProfitCentreID = b.ProfitCentreID and a.DateOfSale >= b.DateOfSale
group by a.ProfitCentreID, a.DateOfSale
)

功能:Date_GetMonday

create function [dbo].[Date_GetMonday] (@dt smalldatetime)
returns smalldatetime
as
begin
    return dateadd(week, datediff(week, 0, @dt-1), 0)
end

Proc:Alerts_SalesReport

create proc Alerts_SalesReport
as

set nocount on 

declare @StartDate_CW smalldatetime
declare @EndDate_CW smalldatetime
declare @StartDate_LW smalldatetime
declare @EndDate_LW smalldatetime
declare @StartDate_LY smalldatetime
declare @EndDate_LY smalldatetime       

-- sort out dates
set @EndDate_CW = dateadd(day, -1, Util.dbo.Date_RoundToDay(getdate())) -- yesterday
set @StartDate_CW = Util.dbo.Date_GetMonday(@EndDate_CW)
set @StartDate_LW = dateadd(day, -7, @StartDate_CW)
set @EndDate_LW = dateadd(day, -7, @EndDate_CW)
set @StartDate_LY = dateadd(week, -52, @StartDate_CW)
set @EndDate_LY = dateadd(week, -52, @EndDate_CW)

-- get sales
select 
ProfitCentreName Branch,
cw.DailySales, 
coalesce(ly.DailySales, lw.DailySales, 0) DailyLFL, 
cw.DailySales - coalesce(ly.DailySales, lw.DailySales, 0) DailyVar, 
cw.WTDSales, 
coalesce(ly.WTDSales, lw.WTDSales, 0) WTD_LFL, 
cw.WTDSales - coalesce(ly.WTDSales, lw.WTDSales, 0) WTDVar, 
cast(isnull(ly.DailySales, 0) as bit) LFL
from ProfitCentreNames pn 
inner join dbo.Alerts_WTDSales(@StartDate_CW, @EndDate_CW) cw on pn.ProfitCentreID = cw.ProfitCentreID
left outer join dbo.Alerts_WTDSales(@StartDate_LW, @EndDate_LW) lw on cw.ProfitCentreID = lw.ProfitCentreID and dateadd(day, -7, cw.DateOfSale) = lw.DateOfSale
left outer join dbo.Alerts_WTDSales(@StartDate_LY, @EndDate_LY) ly on cw.ProfitCentreID = ly.ProfitCentreID and dateadd(week, -52, cw.DateOfSale) = ly.DateOfSale
where cw.DateOfSale = @EndDate_CW
order by pn.ProfitCentreName, cw.DateOfSale

如果您只是复制并粘贴它,我不确定它是否会立即起作用,但您应该能够掌握逻辑。