Есть ли способ ускорить этот запрос, собирая информацию о клиентах?Есть ли лучший метод для этих данных? - PullRequest
0 голосов
/ 05 июня 2019

У меня длинный запрос, но я постараюсь разбить его на части.

Во-первых, есть переменные,

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

У кого-нибудь есть какие-нибудь советы для меня? Есть ли лучший способ сделать это?

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