Запрос продаж LFL в SQL - PullRequest
1 голос
/ 16 июля 2009

Это может показаться чем-то вроде вопроса «сделай домашнее задание для меня» (и это так), но я думаю, что результаты продаж, которые я пытаюсь получить, являются довольно общими и будут полезны для всех, кто занимается продажами отчетности.

У меня есть базовая таблица Sales (поля: Branch , DateOfSale , SalesAmount ) в SQL Server 2005, и мне нужно построить отчет с данными в этой таблице. Мне нужен 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. Сегодняшняя дата - среда, 16 июля 2009 г.

Требуемый результат

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 год назад. Не в этот день, как в 15 июля, а в среду на 29-й неделе (то есть 16 июля). Если этому филиалу меньше года (например, филиал в Кейптауне), используйте продажи за последние недели (т.е. ср. На прошлой неделе). Если на прошлой неделе продаж не было, то ноль.

WTD : неделя до даты. Продажи подведены с понедельника на этой неделе до вчерашнего дня. Итак, пн, вт, ср в моем примере.

WTD LFL : Неделя-на-дату Та же логика, что и у LFL, но на этот раз с WTD вместо ежедневных продаж

LFL : Битовый флаг показывает, могли ли мы использовать LFL (значение: 1) или должны были использовать продажи за последние недели (значение: 0)

Поскольку это стандартные показатели розничных продаж, я надеюсь, что кто-то уже написал для них SQL. Может быть, не бит «если у тебя нет прошлого года, потом использовать последнюю неделю», но определенно LFL и WTD.

Если для решения требуется таблица календаря (например, http://tinyurl.com/nt5gck),, это нормально.

1 Ответ

1 голос
/ 27 июля 2009

У меня нет хороших ответов, поэтому я должен был сделать это сам. Ради полноты, вот мой ответ.

Обратите внимание, что в ответе используется реальное имя таблицы в моей базе данных (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

Я не уверен, сработает ли это сразу, если вы просто скопируете и вставите его, но вы должны быть в состоянии понять логику.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...