Sql-Server
從具有多個關係的兩個表中進行選擇的最佳做法是什麼?
SELECT (SELECT Name FROM Management_EnumerableItem ME WHERE ME.ID = DN) DN, (SELECT Name FROM Management_EnumerableItem ME WHERE ME.ID = PN) PN, (SELECT Name FROM Management_EnumerableItem ME WHERE ME.ID = Winder) Winder, (SELECT Name FROM Management_EnumerableItem ME WHERE ME.ID = CouplingType) CouplingType, (SELECT Name FROM Management_EnumerableItem ME WHERE ME.ID = Type) Type, (SELECT Name FROM Management_EnumerableItem ME WHERE ME.ID = ILayer) ILayer, (SELECT Name FROM Management_EnumerableItem ME WHERE ME.ID = OLayer) OLayer FROM Product_Coupling_Serial
那麼,對於這樣的選擇(最快的方式),獲得最佳性能的最佳實踐是什麼?
在 Id 列上創建覆蓋索引並在表 Management_EnumerableItem 上包含名稱。
CREATE INDEX IDX_Name on Management_EnumerableItem (Id) Include (Name) with (fillfactor=90);
並這樣寫。
SELECT A.NAME, B.NAME, C.NAME, D.NAME, E.NAME, F.NAME, G.NAME, FROM Product_Coupling_Serial P LEFT OUTER JOIN Management_EnumerableItem A ON A.ID = P.DN LEFT OUTER JOIN Management_EnumerableItem B ON B.ID = P.PN LEFT OUTER JOIN Management_EnumerableItem C ON C.ID = P.Winder LEFT OUTER JOIN Management_EnumerableItem D ON D.ID = P.CouplingType LEFT OUTER JOIN Management_EnumerableItem E ON E.ID = P.[Type] LEFT OUTER JOIN Management_EnumerableItem F ON F.ID = P.[ILayer] LEFT OUTER JOIN Management_EnumerableItem G ON G.ID = P.[OLayer]
謝謝
請考慮嘗試此查詢,並讓我知道它的執行情況。
WITH EnumerableItemNames AS ( SELECT PcsID = pcs.ID, v.ColName, ItemName = me.Name FROM dbo.Product_Coupling_Serial pcs CROSS APPLY (VALUES ('DN', pcs.DN), ('PN', pcs.PN), ('Winder', pcs.Winder), ('CouplingType', pcs.CouplingType), ('Type', pcs.[Type]), ('ILayer', pcs.ILayer), ('OLayer', pcs.OLayer) ) v (ColName, EnumerableItemID) LEFT JOIN dbo.Management_EnumerableItem me ON v.EnumerableItemID = me.ID ) SELECT p.DN, p.PN, p.Winder, p.CouplingType, p.[Type], p.ILayer, p.OLayer FROM EnumerableItemNames ein PIVOT ( Max(ein.ItemName) FOR ein.ColName IN (DN, PN, Winder, CouplingType, [Type], ILayer, OLayer) ) p ;
雖然理論上它可能在性能上完全失敗,但我也認為它最終可能會表現得更好。如果不是更好,您仍然可以通過將 CTE 的結果(沒有 LEFT JOIN to
Management_EnumerableItem
)插入到帶有一些精心選擇的索引的臨時表中,然後使用臨時表進行第二次查詢來獲得它. 它確實有點取決於您查詢表的準確程度、它有多少行、它們有多寬、有多少結果行等等。如果您需要表中的更多列
Product_Coupling_Serial
,那麼您可以嘗試在 CTE 中包含這些列,但這可能會通過增加數據透視操作所需的記憶體來嚴重影響性能,因此您也可以在最後加入它:// CTE here... SELECT pcs.Year, pcs.ProductCode, pcs.QRText, pcs.UniqueSerial, ... p.DN, p.PN, p.Winder, p.CouplingType, p.[Type], p.ILayer, p.OLayer FROM EnumerableIDs ei PIVOT ( Max(ei.ItemName) FOR ei.ColName IN (DN, PN, Winder, CouplingType, [Type], ILayer, OLayer) ) p INNER JOIN dbo.Product_Coupling_Serial pcs ON ei.PcsID = pcs.ID ;