加入導致其他列數據發生變化?
我首先要說我對數據庫和 SQL 比較陌生,我正在嘗試對以前同事創建的a
View
進行補充。SQL Server
我正在嘗試加入
Customer_Snacks
表格,以便我可以獲得Snack Quantity
每個客戶的訂單。我遇到的問題是LEFT OUTER JOIN
,據我所知,當我執行某個操作時,其他一些列數據會發生巨大變化。通過使用子查詢,我設法讓它以我希望的方式工作,但它非常慢。查詢需要一分鐘多的時間才能執行,作為回報,呼叫該視圖的應用程序會超時。
這是我目前擁有的作品(我知道,這很混亂):
SELECT cl.CustomerID, cl.FirstName + ' ' + c.LastName as CustomerDisplay, cl.InvoiceID, cl.MealPlanID, mp.DeliveryDate1 as DeliveryDate, SUM(CASE WHEN cll.Name = 'Meal' THEN cll.Quantity ELSE 0 END) as RegularQuantity, SUM(CASE WHEN cll.Name = 'Meal' THEN cll.Quantity * Amount ELSE 0 END) as RegularTotal, SUM(CASE WHEN cll.Name = 'EXTRAPROTEINMEAL' THEN cll.Quantity ELSE 0 END) as ProteinQuantity, SUM(CASE WHEN cll.Name = 'EXTRAPROTEINMEAL' THEN cll.Quantity * Amount ELSE 0 END) as ProteinTotal, SUM(CASE WHEN cll.Name = 'TAX' THEN Amount ELSE 0 END) as TotalTax, SUM(CASE WHEN cll.Name = 'SNACKS' THEN Amount ELSE 0 END) AS SnackTotal, -- Here is my subquery that I would like to integrate into this view with a join so that it's much faster (SELECT SUM(cs.Quantity) FROM Fustomer_Snacks as cs WHERE cs.CustomerID = cl.CustomerID and cs.DeliveryDate = mp.DeliveryDate1) as SnackQuantity, ------------------------------------------------------------------ CAST(SUM((CASE WHEN cll.Name = 'home' or cll.Name = 'work' THEN 1 ELSE 0 END)) as bit) as IsDelivery, SUM(CASE WHEN (cll.Name = 'home' or cll.Name = 'work' or cll.Name = 'pickup') and cll.Quantity > 0 THEN cll.Quantity * Amount else 0 END) as DeliveryCharge, cl.Balance as PrePromoTotal, ISNULL(cl.Balance * (pc.Discount * .01), 0) * -1 as PromoDiscount, cl.FinalBalance - ISNULL((cl.FinalBalance * (pc.Discount * .01)),0) Total FROM Customer_Ledger as cl INNER JOIN Customer_Ledger_LineItems as cll on cl.ID = cll.LedgerID INNER JOIN MealPlan as mp on cl.MealPlanID = mp.ID INNER JOIN Customer as c on cl.CustomerId = c.Id LEFT OUTER JOIN PromoCode as pc on cl.BalancePromoId = pc.Id GROUP BY cl.CustomerID, c.FirstName, c.LastName, MealPlanID, InvoiceID, mp.DeliveryDate1, cl.Balance, cl.FinalBalance, pc.Discount
就像我說的,我目前擁有它的方式,它可以工作,但它太慢了。一旦我嘗試
LEFT OUTER JOIN
它,它就會快得多,但其他列就像RegularQuantity
其他數字一樣被誇大了(我不確定這是怎麼發生的)。如果有人能引導我朝著正確的方向前進,那就太好了!
GROUP BY
很可能你的問題是,當你添加零食時,你有不止一張表為你的語句中的列返回不止一行- 可能Customer_Snacks
和Customer_Ledger_LineItems
。當數據庫引擎執行連接時,它會匹配第一個表中的許多行與值ABC,但第二個表中的許多行具有相同的值ABC(外部連接的工作方式略有不同,但我們暫時忽略它) .
我猜對於給定的
Customer_Ledger
行,您將綁定到Customer
一行、MealPlan
一行、一(或零)PromoCode row, and multiple
個 Customer_Ledger_LineItems 行。我也在猜測
Customer_Ledger
一行及其相關MealPlan
行,您可以帶回多Customer_Snacks
行。因此,當我們將所有行放在一起時,假設我們有:
- 1
Customer
行- 1
Customer_Ledger
行- 1
MealPlan
行- 1
PromoCode
行- 3
Customer_Ledger_LineItems
行將所有這些匹配在一起,你得到
1 * 1 * 1 * 1 * 3
= 3 行。現在,添加 2
Customer_Snacks
行。這些與我們已經擁有的所有行匹配,所以我們得到1 * 1 * 1 * 1 * 3 * 2
= 6 行。當我們去取我們的總和時,我們將從
Customer_Ledger_LineItems
行中得到雙倍的總和,因為現在每行顯示兩次。而且,我們將從 中得到三倍的總和Customer_Snacks
,因為這些行現在每行都顯示了 3 次。基本上,您在CROSS JOIN
相關Customer_Ledger_LineItems
行和Customer_Snacks
行之間得到一個。有兩種方法可以避免這種情況。您已經使用了第一個選項 - 使用子查詢從一個表中獲取總和,該表將多行返回到我們的分組值。
另一個選項非常相似:建構一個包含您需要的所有相關值的臨時表(或 CTE),這樣當您加入數據時,您將只有一行包含所需的總和。在您的情況下,這看起來像:
;WITH SnackSums AS (SELECT cs.CustomerID ,cs.DeliveryDate ,SUM(cs.Quantity) as SnackQuantity FROM Customer_Snacks cs GROUP BY cs.CustomerID, cs.DeliveryDate )
並且會在
SELECT
您的查詢之前進行。然後,您只需將ss.SnackQuantity
子查詢放在哪裡,然後添加:LEFT OUTER JOIN SnackSums ss ON (cl.CustomerId = ss.CustomerId AND ss.DeliveryDate = mp.DeliveryDate1)
就在你的
GROUP BY
. 最後,您還需要添加ss.SnackQuantity
,GROUP BY
因為在您的主查詢的上下文中,這是一個獨立的非聚合值。現在,我不保證這會比子查詢更快。然而,它應該是準確的——如果它不准確的話,那也不要緊。