2012-07-24 177 views
0

我從幾個表中選擇數據,但主要想法是產品可能有也可能沒有與之相關的折扣記錄,如折扣或美元折扣金額。我正在使用左外連接(這可能不正確),並且無論是否存在記錄,都會返回相同的美元值和百分比值。左外部加入丟失的記錄

查詢看起來像:

SELECT Items.ItemID, Items.name, Items.price, 
     ItemDiscounts.percentOff, ItemDiscounts.dollarOff, 
     ItemAttributes.ColorName, ItemStuff.StuffID 
FROM Items, ItemAttributes, ItemStuff 
LEFT OUTER JOIN ItemDiscounts 
    ON ItemDiscounts.ItemID = ItemID 
    AND (
    ItemDiscounts.percentOff > 0 
    OR ItemDiscounts.dollarOff > 0 
) 
WHERE Items.ItemID = ItemAttributes.ItemID 
AND ItemStuff.ItemID = Items.ItemID 
GROUP BY ItemStuff.StuffID 

怪異的是,在所有的結果,percentOff返回「1」,而dollarOff返回「0」,不管每個項目都有它自己的相關折扣紀錄。對於吐痰,我將ItemDiscounts.percentOff > 0更改爲ItemDiscounts.percentOff > 1,然後將dollarAmount更改爲全部2,percentOff全部爲0。

我對此有些困惑,所以任何幫助將不勝感激。

+0

是否存在GROUP BY '或任何聚合函數(SUM,COUNT ..)在這裏沒有顯示? – Vatev 2012-07-24 18:37:37

+0

有一個GROUP BY,是的,我嘲笑查詢使它更短並且不暴露實際的表/列名,將編輯顯示組 – 2012-07-24 18:39:51

+0

試試選擇GROUP_CONCAT(ItemDiscounts.dollarOff)而不是ItemDiscounts.dollarOff來查看GROUP BY是否隱藏其中任何一個 – Vatev 2012-07-24 18:46:47

回答

1

您在ON子句中具有對ItemID的非限定引用......不清楚爲什麼這不會引發「模糊列」異常。 (顯然,這不是曖昧到MySQL,而MySQL是確定哪些被引用項目Id,賠率是好的,它不是一個你意。

此外,查詢包括對ItemStuff行來源的引用,但沒有

我還懷疑GROUP BY的行爲給你的結果集不符合你的期望(很可能,現在,它掩蓋了你的真實問題查詢,這可能是您沒有打算的CROSS JOIN操作。

我建議您在沒有的情況下嘗試查詢子句,並確認結果集是您期望缺少GROUP BY子句的內容。

注意:大多數其他關係數據庫引擎將拋出異常,並顯示GROUP BY,就像您在查詢中顯示的那樣。他們(基本上)要求SELECT列表中的每個非聚集都包含在GROUP BY中。你可以讓MySQL以相同的方式行事(使用sql_mode的一些特定設置)。MySQL更加自由,但是你找回的結果可能不符合你的期望。

注意:我沒有看到這個查詢是如何傳遞語義檢查的,並且根據給定的不存在的ItemStuff行源的引用返回任何結果集。


爲了提高可讀性,我建議您不要使用逗號作爲連接運算符,而是使用JOIN關鍵字。我還建議您將WHERE子句中的連接謂詞移至ON子句。我還希望給每個行源一個別名,並使用該別名來限定它的列。

給你展示在您的查詢,我會寫(部分我可以做的意義上)這樣的內容:

SELECT i.ItemID 
    , i.name 
    , i.price 
    , d.percentOff 
    , d.dollarOff 
    , a.ColorName 
    FROM Items i 
    JOIN ItemAttributes a 
    ON a.ItemID = i.ItemID 
    LEFT 
    JOIN ItemDiscounts d 
    ON d.ItemID = i.ItemID 
     AND (d.percentOff > 0 OR d.dollarOff > 0) 

我省略選擇列表ItemStuff.StuffID,因爲我不請參閱任何ItemStuff行源。

我也排除WHERE子句,因爲在查詢中沒有看到任何ItemStuff rowsource。

-- WHERE ItemStuff.ItemID = i.ItemID 

我省略了GROUP BY,因爲,再說,我沒有看到你所查詢的任何ItemStuff行來源,而且由於GROUP BY的行爲很可能不是我所期望的,而是被掩蓋的問題我的查詢。

-- GROUP BY ItemStuff.StuffID 

UPDATE:

@Kyle,您的查詢「超時」這一事實讓我相信你生成WAY更多的行比預期的,就像你有一個笛卡爾乘積(表中的每一行都與另一個表中的每一行「匹配」......一個表中的每行10,000行,另一個表中的10,000行將生成100,000,000行

我認爲GROUP BY子句是屏蔽真正的問題EM。

我建議在開發時將每個表的PRIMARY KEY作爲結果集中的主要列。我會在驅動表中添加一些合理的謂詞(例如,i.ItemID IN (2,3,5,7)限制結果集的大小,以及ORDER BY主鍵...應該有助於識別意外的笛卡爾積。

+0

缺少ItemStuff是打字錯誤。簡單地刪除GROUP BY使查詢超時,我將考慮將WHERE子句移入連接 – 2012-07-24 19:08:17

+0

@凱爾,事實上你的查詢「超時」使我相信你正在產生比你期望的更多的行,就像你有一個笛卡爾積(表中的每一行都被「匹配」到其他表中的每一行...一個表中有10,000行,另一個表中有10,000行,這將產生100,000,000行。 'GROUP BY'掩蓋了你的問題。 – spencer7593 2012-07-24 19:11:51

+0

是的。我更深入地研究了它,並且GROUP BY被另一個開發者放在那裏,以掩蓋這樣一個事實,即所謂的「一對一」關係實際上是「一對多」的關係。實際上,我們10年前的數據庫已經遠遠沒有正常化,我可能不得不採取不同的路線。我會接受你的回答,因爲對於有類似問題的人來說,這似乎最有幫助。感謝您的幫助。 – 2012-07-24 19:19:42

0

當你從查詢中刪除這些行時,你會得到你想要的嗎?

AND( ItemDiscounts.percentOff> 0 OR ItemDiscounts.dollarOff> 0 )

+0

相同的結果... 1對於'percentOff',0對於'dollarOff' – 2012-07-24 18:38:09

0

一旦您指定外的可能空方的絕對值加入,您WHERE條款必須考慮到它。

與下列條款試試:

AND (
ItemDiscounts.percentOff > 0 
OR ItemDiscounts.percentOff is null 
OR ItemDiscounts.dollarOff > 0 
OR ItemDiscounts.dollarOff is null 
) 

Additionaly,你指定一個GROUP BY沒有彙總。這在大多數情況下是沒有意義的。你可能想要ORDER BY排序。