Как я могу оптимизировать мой запрос MySQL, преобразованный из SQL Server? - PullRequest
0 голосов
/ 26 апреля 2019

У меня был запрос MS SQL, который раньше выполнялся очень быстро, но мы перешли на MySQL, и мне пришлось пересобрать запрос MS SQL в MySQL, но я столкнулся с некоторой проблемой, поскольку MySQL не поддерживает Full Join.Я поработал вокруг, и он продолжает работать (все нормально до последнего соединения (X), я думаю, что загрузка будет длиться вечно).

Как я могу улучшить этот запрос?

SQL-запрос:

WITH BadInvoiceCTE AS (
    SELECT 
        COALESCE(P.InvoiceNumber, C.InvoiceNumber) [InvoiceNumber]
    FROM (
        SELECT 
            InvoiceNumber
            ,COUNT(SK.Sku) [SkuCount]
        FROM InvoiceDetail ID
            LEFT JOIN tardis.Skus SK ON SK.EntityID = ID.Sku_EntityID
        WHERE SK.Sku IN ('BPPRNS000037', 'BPPRNS000029', 'BPPRNS000030')
            AND ID.DivisionID = 3
            AND ID.ActivityDate >=  '2018-02-04'
            AND SK.LevelSix = 'GLASS'
        GROUP BY InvoiceNumber
    ) P
    FULL JOIN (
        SELECT 
            InvoiceNumber 
            ,COUNT(SK.Sku) [SkuCount]
        FROM InvoiceDetail ID
            LEFT JOIN tardis.Skus SK ON SK.EntityID = ID.Sku_EntityID
        WHERE SK.Sku IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046')
            AND ID.DivisionID = 3
            AND ID.ActivityDate >=  '2018-02-04'
            AND SK.LevelSix = 'GLASS'
        GROUP BY InvoiceNumber
    ) C ON C.InvoiceNumber = P.InvoiceNumber
    WHERE ISNULL(P.SkuCount,0) <> ISNULL(C.SkuCount,0)
)   

SELECT
    Id.ActivityDate [InvoiceDate]
    ,ID.InvoiceNumber
    ,ST.Store
    ,SK.[Product Description] [ProductName] 
    ,SK.Sku [SKU]
    ,SK.LevelThree
    ,SK.LevelFour
    ,SK.LevelFive
    ,SK.LevelSix
    ,ID.Price
    ,EM.[Name] [SalesPerson]
    , CONVERT(FLOAT,SUM(CASE WHEN X.Sku ='BPPRNS000037' AND SK.Sku IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046') THEN ID.Quantity END)) [WarrantyCorrect]
    , CONVERT(FLOAT,SUM(CASE WHEN X.Sku ='BPPRNS000029' AND SK.Sku IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046') THEN ID.Quantity END)) [BlackIceInstallErrorCorrect]
    , CONVERT(FLOAT,SUM(CASE WHEN X.Sku ='BPPRNS000030' AND SK.Sku IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046') THEN ID.Quantity END)) [DefectiveItem]
FROM
    BadInvoiceCTE BI
    INNER JOIN dbo.InvoiceDetail ID ON ID.InvoiceNumber = BI.InvoiceNumber
    LEFT JOIN tardis.Skus SK ON SK.EntityID = ID.Sku_EntityID
    LEFT JOIN dbo.Stores ST ON ST.EntityID = ID.Store_EntityID
    LEFT JOIN tardis.Employees EM ON EM.EntityID = ID.Employee_EntityID
    LEFT JOIN   (       
        SELECT 
            InvoiceNumber 
            ,Sku
        FROM InvoiceDetail ID
            LEFT JOIN tardis.Skus SK ON SK.EntityID = ID.Sku_EntityID
        WHERE SK.Sku IN ('BPPRNS000037', 'BPPRNS000029', 'BPPRNS000030')
            AND ID.DivisionID = 3
            AND ID.ActivityDate >=  '2018-02-04'
            AND SK.LevelSix = 'GLASS'
    ) X ON X.InvoiceNumber = ID.InvoiceNumber
WHERE
    ID.DivisionID = 3
    AND ID.ActivityDate >=  '2018-02-04'
    AND SK.LevelSix = 'GLASS'
GROUP BY 
     ID.ActivityDate 
    ,ID.InvoiceNumber
    ,ST.Store
    ,SK.[Product Description] 
    ,SK.Sku
    ,SK.LevelThree
    ,SK.LevelFour
    ,SK.LevelFive
    ,SK.LevelSix
    ,ID.Price
    ,EM.[Name]
ORDER BY ID.InvoiceNumber

MySQL-запрос, который я перестроил

WITH BadInvoiceCTE AS (
    SELECT 
        COALESCE(P.InvoiceIDByStore, C.InvoiceIDByStore) 'InvoiceNumber'
    FROM
    (
        SELECT
              P.InvoiceIDByStore
            , COUNT(SK.ID) 'SkuCount'
        FROM 
            simplymacstaging.productdetail P
            LEFT JOIN simplymacstaging.sku_view Sk ON Sk.ID = P.ProductIdentifier
        WHERE CONVERT(DateCreated, Date) >= '2019-02-03'
            AND Sk.Level6 = 'GLASS'
            AND SK.ID IN ('BPPRNS000037', 'BPPRNS000029', 'BPPRNS000030')
        GROUP BY  P.InvoiceIDByStore
    ) P
    Left Join (
        SELECT
              P.InvoiceIDByStore
            , COUNT(SK.ID) 'SkuCount'
        FROM 
            simplymacstaging.productdetail P
            LEFT JOIN simplymacstaging.sku_view Sk ON Sk.ID = P.ProductIdentifier
        WHERE CONVERT(DateCreated, Date) >= '2019-02-03'
            AND Sk.Level6 = 'GLASS'
            AND SK.ID IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046')
        GROUP BY  P.InvoiceIDByStore
    ) C ON C.InvoiceIDByStore = P.InvoiceIDByStore
      WHERE ifnull(P.SkuCount,0) <> ifnull(C.SkuCount,0)
    UNION
    SELECT 
        COALESCE(P.InvoiceIDByStore, C.InvoiceIDByStore) 'InvoiceNumber'
    FROM
    (
        SELECT
              P.InvoiceIDByStore
            , COUNT(SK.ID) 'SkuCount'
        FROM 
            simplymacstaging.productdetail P
            LEFT JOIN simplymacstaging.sku_view Sk ON Sk.ID = P.ProductIdentifier
        WHERE CONVERT(DateCreated, Date) >= '2019-02-03'
            AND Sk.Level6 = 'GLASS'
            AND SK.ID IN ('BPPRNS000037', 'BPPRNS000029', 'BPPRNS000030')
        GROUP BY  P.InvoiceIDByStore
    ) P
    right Join (
        SELECT
              P.InvoiceIDByStore
            , COUNT(SK.ID) 'SkuCount'
        FROM 
            simplymacstaging.productdetail P
            LEFT JOIN simplymacstaging.sku_view Sk ON Sk.ID = P.ProductIdentifier
        WHERE CONVERT(DateCreated, Date) >= '2019-02-03'
            AND Sk.Level6 = 'GLASS'
            AND SK.ID IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046')
        GROUP BY  P.InvoiceIDByStore
    ) C ON C.InvoiceIDByStore = P.InvoiceIDByStore
      WHERE ifnull(P.SkuCount,0) <> ifnull(C.SkuCount,0)
)
SELECT 
      Convert(ID.DateCreated, Date) 'InvoiceDate'
    , ID.InvoiceIDByStore
    , ID.InvoicedAt
    , Sk.Description
    , Sk.ID 'ProductName'
    , SK.Level3
    , SK.Level4
    , SK.Level5
    , SK.Level6
    , ID.TotalPrice
    , ID.EmployeeName
   # , SUM(CASE WHEN X.ID ='BPPRNS000037' AND SK.ID IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046') THEN ID.Quantity END) 'WarrantyCorrect'
FROM
    BadInvoiceCTE BI
    INNER JOIN simplymacstaging.productdetail ID ON ID.InvoiceIDByStore = BI.InvoiceNumber
    LEFT JOIN simplymacstaging.sku_view Sk ON Sk.ID = ID.ProductIdentifier
    LEFT JOIN (
        SELECT
          P.InvoiceIDByStore
        , Sk.ID
        FROM
            simplymacstaging.productdetail P
            LEFT JOIN simplymacstaging.sku_view Sk ON Sk.ID = P.ProductIdentifier
        WHERE CONVERT(DateCreated, Date) >= '2019-02-03'
            AND Sk.Level6 = 'GLASS'
            AND SK.ID IN ('BPPRNS000037', 'BPPRNS000029', 'BPPRNS000030')
    ) X ON X.InvoiceIDByStore = ID.InvoiceIDByStore
WHERE
    CONVERT(ID.DateCreated, Date) >= '2019-02-03'
    AND Sk.Level6 = 'GLASS'
GROUP BY
    Convert(ID.DateCreated, Date)
    , ID.InvoiceIDByStore
    , ID.InvoicedAt
    , Sk.Description
    , Sk.ID 
    , SK.Level3
    , SK.Level4
    , SK.Level5
    , SK.Level6
    , ID.TotalPrice
    , ID.EmployeeName

Ответы [ 2 ]

0 голосов
/ 30 апреля 2019

Добавление к ответу @ Uueerdo:

WHERE CONVERT(DateCreated, Date) >= '2019-02-03'

-> (при условии, что DateCreated имеет тип DATE или DATETIME или TIMESTAMP)

WHERE DateCreated >= '2019-02-03'

И

COUNT(CASE WHEN SK.ID IN (...) THEN 1 ELSE NULL END

-> (более кратко, хотя и нестандартно)

SUM(SK.ID IN (...))

У вас есть этот составной индекс?

INDEX(Level6, ID, DateCreated??)

(Если DateCreated не в Sk, оставьте его выключенным)

0 голосов
/ 26 апреля 2019

Вы, вероятно, можете упростить весь CTE с помощью условного агрегирования, например, так:

SELECT P.InvoiceIDByStore
    , COUNT(CASE WHEN SK.ID IN ('BPPRNS000037', 'BPPRNS000029', 'BPPRNS000030') THEN 1 ELSE NULL END
        ) 'SkuCount1'
    , COUNT(CASE WHEN SK.ID IN ('BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046') THEN 1 ELSE NULL END
        ) 'SkuCount2'
FROM simplymacstaging.productdetail P
LEFT JOIN simplymacstaging.sku_view Sk ON Sk.ID = P.ProductIdentifier
WHERE CONVERT(DateCreated, Date) >= '2019-02-03'
    AND Sk.Level6 = 'GLASS'
    AND SK.ID IN (
        'BPPRNS000037', 'BPPRNS000029', 'BPPRNS000030'
        , 'BPPRGG000027', 'BPPRGG000026', 'BPPRGG000035', 'BPPRGG000036', 'BPPRGG000045', 'BPPRGG000046'
    )
GROUP BY P.InvoiceIDByStore
HAVING SkuCount1 <> SkuCount2

... и уточнить то, что я сказал в комментарии, LEFT JOIN с учетом "X" (на InvoiceNumberв отдельности), а не "SK" напрямую (в отношении идентификатора продукта и условий WHERE для X) кажется, что это будет полукросс-произведение деталей.

...