У меня длинный запрос, но я постараюсь разбить его на части.
Во-первых, есть переменные,
DECLARE @LocalCompanyCode VARCHAR(5)
SET @LocalCompanyCode = '09'
DECLARE @LocalDivisionCode VARCHAR(5)
SET @LocalDivisionCode = '001'
DECLARE @CustomerBaseFromDate DATETIME --CustomerBase
SET @CustomerBaseFromDate = '1/1/2019'
DECLARE @CustomerBaseToDate DATETIME
SET @CustomerBaseToDate = '5/30/2019'
DECLARE @RecurringBaseFromDate DATETIME --Recurring Base
SET @RecurringBaseFromDate = '1/1/2018'
DECLARE @RecurringBaseToDate DATETIME
SET @RecurringBaseToDate = '1/1/2019'
DECLARE @LifetimeBaseFromDate DATETIME --Lifetime Base
SET @LifetimeBaseFromDate = '1/1/2015'
DECLARE @LifetimeBaseToDate DATETIME
SET @LifetimeBaseToDate = '1/1/2018'
Код компании и код подразделения, выберите компанию, для которой мы выполняем этот запрос. База клиентов будет базой клиентов, на которую мы будем смотреть. Так что в нашем примере это последние 5 месяцев.
Таким образом, для всех клиентов за последние 5 месяцев мы будем искать на нашей повторяющейся базе. Это модульное решение, поэтому мы можем контролировать время, прежде чем считать клиента «потерянным». Мы сравним с повторяющейся базой и посмотрим, сколько клиентов являются новыми клиентами, которые заказывали только один раз за клиентскую и повторяющуюся базу, и сколько клиентов являются постоянными клиентами, тех, кто заказывал несколько раз за эти периоды.
Тогда у нас также будет жизненная база. Мы будем проверять клиентов, которые заказывали один или несколько раз в течение срока нашей базы, не делали заказы на нашей постоянной базе, но делали заказ снова в нашей базе за 5 месяцев. Это подсчитывает, сколько клиентов были «повторно активированы» или были признаны потерянными, но недавно купили у нас снова.
Тогда я объявляю четыре таблицы
DECLARE @FullBase TABLE
(
Date_Created DATE,
Company_Code VARCHAR(2),
Division_Code VARCHAR(3),
Invoice_Number VARCHAR(50),
CUST_PO VARCHAR(50),
Total_Quantity NUMERIC,
TotalPrice MONEY,
City VARCHAR(50),
State VARCHAR(50),
Zip VARCHAR(50),
CountryCode VARCHAR(50),
Month NUMERIC,
CustomerEmail VARCHAR(MAX),
OrderCountBase NUMERIC,
TotalOrdersBase NUMERIC
)
DECLARE @LifetimeBase TABLE
(
Date_Created DATE,
Company_Code VARCHAR(2),
Division_Code VARCHAR(3),
Invoice_Number VARCHAR(50),
CUST_PO VARCHAR(50),
Total_Quantity NUMERIC,
TotalPrice MONEY,
City VARCHAR(50),
State VARCHAR(50),
Zip VARCHAR(50),
CountryCode VARCHAR(50),
Month NUMERIC,
CustomerEmail VARCHAR(MAX),
OrderCountLifetimeBase NUMERIC,
TotalOrdersLifetimeBase NUMERIC
)
DECLARE @RecurringBase TABLE
(
Date_Created DATE,
Company_Code VARCHAR(2),
Division_Code VARCHAR(3),
Invoice_Number VARCHAR(50),
CUST_PO VARCHAR(50),
Total_Quantity NUMERIC,
TotalPrice MONEY,
City VARCHAR(50),
State VARCHAR(50),
Zip VARCHAR(50),
CountryCode VARCHAR(50),
Month NUMERIC,
CustomerEmail VARCHAR(MAX),
OrderCountRecurringBase NUMERIC,
TotalOrdersRecurringBase NUMERIC
)
DECLARE @CustomerBase TABLE
(
Date_Created DATE,
Company_Code VARCHAR(2),
Division_Code VARCHAR(3),
Invoice_Number VARCHAR(50),
CUST_PO VARCHAR(50),
Total_Quantity NUMERIC,
TotalPrice MONEY,
City VARCHAR(50),
State VARCHAR(50),
Zip VARCHAR(50),
CountryCode VARCHAR(50),
Month NUMERIC,
CustomerEmail VARCHAR(MAX),
OrderCountCustomerBase NUMERIC,
TotalOrdersCustomerBase NUMERIC
)
Затем я вставляю всех наших клиентов в «FullBase», с начала Lifetime Base до конца Customer Base
INSERT INTO @FullBase
SELECT Orders.Date_Created
,Orders.Company_Code
,Orders.Division_Code
,Orders.Invoice_Number
,Orders.CUST_PO
,Orders.Total_Quantity
,Orders.Total
,Orders.City
,Orders.State
,Orders.Zip
,Orders.CountryCode
,Orders.Month
,Orders.CustomerEmail
,Row_Number() over (partition by CustomerEmail order by Date_Created asc) OrderCountBase
,Count(*) over (partition by CustomerEmail) TotalOrdersBase
FROM(
Select
CONVERT(Date, OrderCreated) Date_Created
,CONCAT ('0', LEFT(OrderName,1)) Company_Code
,CONCAT ('00', RIGHT(LEFT(OrderName,2),1)) Division_Code
,InvoiceNumber Invoice_Number
,OrderName CUST_PO
,1 Total_Quantity
,TotalPrice Total
,ShippingCity City
,CASE WHEN ShippingCountryCode <> 'US' THEN 'INT' ELSE ShippingProvinceCode END State
,ShippingZip Zip
,ShippingCountryCode CountryCode
,Month( OrderCreated) Month
,Email CustomerEmail
From [SHOPIFY].[shopify_moret].[dbo].orderwrappers O
Where CONVERT(Date, O.OrderCreated) >= Convert(datetime, '05/29/2019')
AND CONCAT ('0', LEFT(O.OrderName,1)) = @LocalCompanyCode--'09'
AND CONCAT ('00', RIGHT(LEFT(O.OrderName,2),1)) = @LocalDivisionCode --'001'
UNION
Select
Archive.Date_Created
,Archive.Company_Code
,Archive.Division_Code
,Archive.Invoice_Number
,('91'+Archive.CUST_PO) CUST_PO
,Archive.Total_Quantity
,Archive.Total
,Archive.City
,Archive.State
,Archive.Zip
,Archive.Country
,Archive.Month
,Archive.CustomerEmail
FROM SpraygroundArchivedOrders Archive
Where Archive.Date_Created < Convert(datetime, '05/29/2019')
) Orders
Where Orders.Date_Created BETWEEN @LifetimeBaseFromDate AND @CustomerBaseToDate
Вот пример того, как выглядят данные:
https://docs.google.com/spreadsheets/d/1wnjVHcPHHnugywa7Qz-aqctaD4cDI5DxehNna0TyaFU/edit?usp=sharing
Затем я использую эту полную базу, чтобы заполнить три другие таблицы порядками из их диапазона.
INSERT INTO @LifetimeBase
SELECT
F.Date_Created
,F.Company_Code
,F.Division_Code
,F.Invoice_Number
,F.CUST_PO
,F.Total_Quantity
,F.TotalPrice
,F.City
,F.State
,F.Zip
,F.CountryCode
,F.Month
,F.CustomerEmail
,Row_Number() over (partition by CustomerEmail order by Date_Created asc) OrderCountLifetimeBase
,Count(*) over (partition by CustomerEmail) TotalOrdersLifetimeBase
FROM @FullBase F
Where F.Date_Created BETWEEN @LifetimeBaseFromDate AND @LifetimeBaseToDate
INSERT INTO @RecurringBase
SELECT
F.Date_Created
,F.Company_Code
,F.Division_Code
,F.Invoice_Number
,F.CUST_PO
,F.Total_Quantity
,F.TotalPrice
,F.City
,F.State
,F.Zip
,F.CountryCode
,F.Month
,F.CustomerEmail
,Row_Number() over (partition by CustomerEmail order by Date_Created asc) OrderCountRecurringBase
,Count(*) over (partition by CustomerEmail) TotalOrdersRecurringBase
FROM @FullBase F
Where F.Date_Created BETWEEN @RecurringBaseFromDate AND @RecurringBaseToDate
INSERT INTO @CustomerBase
SELECT
F.Date_Created
,F.Company_Code
,F.Division_Code
,F.Invoice_Number
,F.CUST_PO
,F.Total_Quantity
,F.TotalPrice
,F.City
,F.State
,F.Zip
,F.CountryCode
,F.Month
,F.CustomerEmail
,Row_Number() over (partition by CustomerEmail order by Date_Created asc) OrderCountCustomerBase
,Count(*) over (partition by CustomerEmail) TotalOrdersCustomerBase
FROM @FullBase F
Where F.Date_Created BETWEEN @CustomerBaseFromDate AND @CustomerBaseToDate
Если я просто выберу * из одной из баз, включая полную базу, выполнение запроса займет всего несколько секунд и вернет 140 000 строк (для @FullBase) всех заказов клиентов.
Однако последняя часть этого запроса, которая выполняется, занимает 10 минут для моих 6-месячных клиентов
SELECT
CC.CustomerEmail
,CC.TotalOrdersCustomerBase
,RC.TotalOrdersRecurringBase
,LC.TotalOrdersLifetimeBase
From
(
SELECT DISTINCT
C.CustomerEmail
,C.TotalOrdersCustomerBase
FROM
@CustomerBase C
) CC
LEFT JOIN
(
SELECT DISTINCT
R.CustomerEmail
,R.TotalOrdersRecurringBase
FROM
@RecurringBase R
) RC ON CC.CustomerEmail = RC.CustomerEmail
LEFT JOIN
(
SELECT DISTINCT
L.CustomerEmail
,L.TotalOrdersLifetimeBase
FROM
@LifetimeBase L
) LC ON CC.CustomerEmail = LC.CustomerEmail
У кого-нибудь есть какие-нибудь советы для меня? Есть ли лучший способ сделать это?