我曾经运行过很快的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
您可以使用条件聚合来简化整个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
ing为“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
,请将其关闭)