2010-11-19 63 views
0

當我有類似下面的HQL東西行:左連接是過濾掉,我希望展示使用HQL

select count(distinct car.id), 
count(distinct w1.id), 
count(distinct w2.id), 
count(distinct w3.id) 
from Car car 
left join Wheel w1 
left join Wheel w2 with w2.IsFrontWheel == true 
left join Wheel w3 with w3.IsFrontWheel == false 
where w1.ManufacturedDate > :manufacturedDate 
and w2.ManufacturedDate > :manufacturedDate 
and w3.ManufacturedDate > :manufacturedDate 
group by car.Make 

這HQL被動態地通過我的用戶的選擇時,他們是在運行報表生成。這裏要注意的重要一點是,用戶正在動態選擇過濾,這會導致此HQL動態構建where子句。

我有where子句生成正常工作。

我的問題是,如果你運行在SQL Server 2008中生成的查詢,最終的結果是,如果有車輪(W1或者W2和W3)不會有任何 ManufacturedDate大於給定參數,該報告完全是,省略了該記錄的

我發現此原因,in this article here

我的問題是,我無法將這些過濾器添加到HQL中的with子句中。通過上面的例子,我可以將約束條件添加到with子句中,但是我創建的報表引擎讓用戶做了比這更高級的過濾,其中大部分內容在with子句中是不允許的。我曾嘗試將一些生成的HQL放入with中,並驗證確實如此,並且大多數查詢不會運行,因爲它們需要對其他表進行額外的約束。

所以我的問題是:

有什麼辦法來修改這個HQL得到了丟失記錄回來?在上面列出的文章中,有人提到如果考慮到NULL,你可以得到記錄,但我不知道他指的是什麼方式,如果這是可能的,我肯定想知道怎麼樣。

UPDATE

我被迫把動態過濾器在where子句中,因爲用戶還可以做這樣的事情:

select count(distinct car.id), 
count(distinct w1.id), 
count(distinct w2.id), 
count(distinct w3.id) 
from Car car 
left join Wheel w1 
left join Wheel w2 with w2.IsFrontWheel == true 
left join Wheel w3 with w3.IsFrontWheel == false 
where w1.Buyer.FirstName = :firstName 
and w2.Buyer.FirstName = :firstName 
and w3.Buyer.FirstName = :firstName 
group by car.Make 

這要是我在改寫與條款

select count(distinct car.id), 
count(distinct w1.id), 
count(distinct w2.id), 
count(distinct w3.id) 
from Car car 
left join Wheel w1 with w1.Buyer.FirstName = :firstName 
left join Wheel w2 with w2.IsFrontWheel == true 
    and w2.Buyer.FirstName = :firstName 
left join Wheel w3 with w3.IsFrontWheel == false 
    and w3.Buyer.FirstName = :firstName 
group by car.Make 

不會運行,NHibernate會拋出異常。

回答

0

時退房 '與' 在HQL關鍵字 click

+0

。我知道有關關鍵字,我的例子甚至使用它,但你不能做的事情,如「與w1.Buyer.id(選擇ID從買家,其中FirstName =:firstName」 – Joseph 2010-11-19 14:06:59

2

你的問題是在WHERE子句中過濾左聯接的列:

select count(distinct car.id), 
count(distinct w1.id), 
count(distinct w2.id), 
count(distinct w3.id) 
from Car car 
left join Wheel w1 
left join Wheel w2 with w2.IsFrontWheel == true 
left join Wheel w3 with w3.IsFrontWheel == false 
where w1.ManufacturedDate > :manufacturedDate --<<<< 
and w2.ManufacturedDate > :manufacturedDate --<<<< 
and w3.ManufacturedDate > :manufacturedDate --<<<< 
group by car.Make 

試試這個:

select count(distinct car.id), 
count(distinct w1.id), 
count(distinct w2.id), 
count(distinct w3.id) 
from Car car 
left join Wheel w1 with w1.ManufacturedDate > :manufacturedDate 
left join Wheel w2 with w2.IsFrontWheel == true AND w2.ManufacturedDate > :manufacturedDate 
left join Wheel w3 with w3.IsFrontWheel == false AND w3.ManufacturedDate > :manufacturedDate 
group by car.Make 

當你比較w2.ManufacturedDate > :manufacturedDate它就像在做null > :manufacturedDate這樣會導致NULL並且行被丟棄,像我一樣t是內連接。將條件移至「左連接」的ON狀態可以防止這種情況發生。

編輯
試試這個:

select count(distinct car.id), 
count(distinct w1.id), 
count(distinct w2.id), 
count(distinct w3.id) 
from Car car 
left join Wheel w1 
left join Wheel w2 with w2.IsFrontWheel == true 
left join Wheel w3 with w3.IsFrontWheel == false 
where ISNULL(w1.ManufacturedDate,'99991231') > :manufacturedDate 
and ISNULL(w2.ManufacturedDate,'99991231)' > :manufacturedDate 
and ISNULL(w3.ManufacturedDate,'99991231') > :manufacturedDate 
group by car.Make 
+0

@KM我已經運行這個和它工作,但對於更復雜的事情,HQL會拋出一個異常,我會更新我的問題以反映導致我問題的HQL。 – Joseph 2010-11-19 14:13:09

+0

@KM您的編輯沒有工作,它仍然過濾掉記錄 – Joseph 2010-11-19 14:19:47

+0

嘗試用''18000101'替換''99991231'' – 2010-11-19 14:54:28

0

我要去潛水,但我不知道HQL :)

什麼,如果你需要避免使用WITH ,那麼當需要計算結果的時候,你需要WHERE子句爲真。這條件是不是從你的問題完全清楚我的事,但這樣的:

where ISNULL(w1.ManufacturedDate, *some_future_value*) > :manufacturedDate 

...其中* some_future_value *你是莫名其妙產生進一步成爲邁向未來比manufacturedDate參數的值。因此,也許你最大的可能日期值,或「:manufacturedDate + 1' ,或任何你的作品

0

嘗試以下操作:

left join Wheel w1 
left join w1.Buyer b1 with b1.FirstName = :firstName 

同所有其他人應該做的

+0

謝謝,但是我得到了與where子句中的相同結果 – Joseph 2010-11-19 17:44:16

+0

那麼,**是在上一個查詢中生成左連接的正確方法。但是,對於你想要獲得的東西來說,這可能還不夠。嘗試編寫查詢應該返回的功能規範。 – 2010-11-19 18:18:25