[英]How can I optimize my MySQL query converted from SQL Server?
我曾经有过运行速度非常快的 MS SQL 查询,但是我们转移到 MySQL 并且我必须在 MySQL 中重建 MS SQL 查询,但是我遇到了一些问题,因为 MySQL 不支持完全连接。 我做了一个解决方法,它一直在运行(一切都很好,直到最后一次加入(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
您可以使用条件聚合来简化整个 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”(在产品标识和 X 的 WHERE 条件上)似乎会形成细节的半交叉产品。
添加到@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
,请将其关闭)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.