如何优化从SQL Server转换的MySQL查询?

问题描述 投票:-1回答:2

我曾经运行过很快的MS SQL查询,但我们转移到了MySQL,我不得不在MySQL中重建MS SQL查询,但由于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
mysql query-performance
2个回答
0
投票

您可以使用条件聚合来简化整个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 JOINing为“X”(仅在InvoiceNumber上),而不是直接对“SK”(在产品标识和X的WHERE条件下)似乎会形成一个半 - 细节的重要产品。


0
投票

添加到@Uueerdo的答案:

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

- >(假设DateCreated的类型为DATEDATETIMETIMESTAMP

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,请将其关闭)

© www.soinside.com 2019 - 2024. All rights reserved.