2010-09-09 193 views
2

我有我無法使用NHibernate標準創建SQL查詢:NHibernate的 「SELECT ... FROM(SELECT ...」 標準

SELECT ID, COLA, COLB, COLC 
FROM table 
WHERE COLC='something' AND ID IN (SELECT ID FROM (SELECT MAX(ID) as ID, COLA FROM table WHERE COLB='something' GROUP BY COLA) subquery) 
ORDER BY ID DESC 

我本來這個稍微簡單查詢:

SELECT ID, COLA, COLB, COLC 
FROM table 
WHERE COLC='something' AND ID IN (SELECT MAX(ID) FROM table WHERE COLB='something' GROUP BY COLA) 
ORDER BY ID DESC 

然而,NHibernate的,如果我用一個「GROUP BY」,它會自動將字段添加到SELECT語句,我沒有阻止它的方式(只要我能找到)。

基本上,我需要找到最新的記錄按任意列分組(在本例中爲「COLA」)。我選擇最大ID來嘗試獲取最新記錄(儘管這可能是其他內容,如「MAX(UPDATED)」)。獲取最新記錄集後,我會進一步過濾它們(「WHERE COLC ='something'」),然後在結果中選擇我需要的列。

如果有更好的方法來獲得相同的結果,我很樂意聽到它。充其量,我的SQL技能是平庸的。

在NHibernate中,我可以得到兩個查詢的權利,但中間的一塊 - 「選擇ID從」,將無法正常工作。

主查詢:

DetachedCriteria.For<table>() 
    .Add<table>(x => x.COLC == "something") 
    .Add(LambdaSubquery.Property<table>(x => x.ID).In(subquery)); 

而且子查詢:

DetachedCriteria.For<table>() 
    .Add<table>(x => x.COLB == "something") 
    .SetProjection(Projections.ProjectionList() 
     .Add(LambdaProjection.Max<table>(x => x.ID)) 
     .Add(LambdaProjection.GroupProperty<table>(x => x.COLA))); 

子查詢標準把「可樂」在選擇列表中(因爲GroupProperty的),所以它自身不可用,這就是爲什麼我需要弄清楚如何在條件中執行「SELECT ID FROM(SELECT ...)」。合併後,它們會生成以下無效SQL(因爲子查詢返回多個列):

SELECT ID, COLA, COLB, COLC 
FROM table 
WHERE COLC='something' AND ID IN (SELECT MAX(ID), COLA FROM table WHERE COLB='something' GROUP BY COLA) 
ORDER BY ID DESC 

編輯:這也可能有助於看到我想要的那種數據和結果:

ID COLA COLB   COLC 
1 1  someone  someother 
2 1  something  someone  (Matches subquery, but not the max. ID) 
3 1  something  something (Matches subquery and main query) 
4 2  someone  something 
5 2  something  someother (Only matches subquery) 
6 3  someone  someother 

我想這裏有最大的ID爲一組給定的「COLA」 S結果, 「COLB」匹配「something」,所以我希望子查詢返回{3,5}。最後,查詢只會返回ID 3的記錄(由於COLC錯誤,外部WHERE子句除去了5)。 COLB和COLC中的實際數據是無關的 - 我只是用它來進一步過濾結果。

我想,在它的核心,我想對每一套COLA

SELECT ID, COLA, COLB 
FROM table 
WHERE ID IN (SELECT MAX(ID) FROM table GROUP BY COLA) 
ORDER BY ID DESC 
+0

你可以顯示你的NHibernate代碼嗎?你想要的查詢究竟是什麼,第二個呢?您幾乎可以使用HQL將其複製並粘貼到NHibernate中。 – rebelliard 2010-09-09 13:09:21

+0

我會很有興趣看到使用LINQ完成這項工作 – Gage 2010-09-09 13:14:02

+0

@Rafael - 我添加了我能夠在NHibernate中工作的內容。理想情況下,我想要第二個查詢,但第一個是可接受的,併產生相同的結果。第一個查詢是一種解決方法,因爲NHibernate總是將組屬性放入SELECT列表中。我避免使用HQL,因爲我不喜歡使用「魔術字符串」。如果我絕對肯定不能以標準來做,那麼我想我沒有太多的選擇。 – Shawn 2010-09-09 13:24:21

回答

2

我找到了一個替代解決方案,因爲我無法弄清楚如何在NHibernate中使用標準API獲得正確的結果 - 使用視圖。

的觀點簡單地使用我原本想查詢(沒有一些額外的過濾):

SELECT ID, COLA, COLB, COLC, ... 
FROM table 
WHERE ID IN 
    (SELECT MAX(ID) 
    FROM table 
    GROUP BY COLA) 

然後,NHibernate的,我映射視圖就像一個普通的表(除了我做到了一成不變):

<class name="View" table="View" lazy="false" mutable="false"> 
    <id name="ID" type="Int32"> 
     <generator class="assigned"/> 
    </id> 
    <property name="COLA" type="String" length="100"> 
     <column name="COLA" /> 
    </property> 
    <property name="COLB" type="String" length="100"> 
     <column name="COLB" /> 
    </property> 
    <property name="COLC" type="String" length="100"> 
     <column name="COLC" /> 
    </property> 
    <!-- Other fields --> 
</class> 

而創建的類映射到:

public class View 
{ 
    public virtual int ID { get; set; } 
    public virtual string COLA { get; set; } 
    public virtual string COLB { get; set; } 
    public virtual string COLC { get; set; } 
    // Other fields 
} 

和最終ly,創建了一個查詢查看:

DetachedCriteria.For<View>() 
    .Add<View>(x => x.COLB == "something") 
    .Add<View>(x => x.COLC == "something") 
    // Any other filtering criteria 
    .AddOrder<View>(x => x.COLA, Order.Desc); 

我寧願在NHibernate中使用單個標準查詢,但是這樣就完成了工作。

2

這樣的最新記錄(最大ID)假設你在尋找有與馬克斯ID的記錄(S)來自COLA的價值,並且還有COLB和相應的MAX ID,你可以使用類似的東西。

var test = 
       ActiveRecordLinq.AsQueryable<table>().Where(
        y => 
        y.COLB == "Something" && 
        y.ID == (from x in ActiveRecordLinq.AsQueryable<table>() 
            where x.COLA == "Something" 
            select x).Max(z => z.ID)) 

我試過這個使用我的一些對象和測試數據,它似乎工作。讓我知道事情的後續。

編輯

馬克斯ID列表可樂,你可以使用此查詢。首先,我會告訴你我正在用於測試的那個,然後你應該看起來像什麼。

我有一個電子郵件組對象,其中包含一個標題和一個TXDX對象,它具有我正在搜索的ID。

var maxes = (from x in ActiveRecordLinq.AsQueryable<Email_Group>() 
        group x by x.Headline 
        into g 
        select new {COLA = g.Key, MaxID = g.Max(z => z.TXDX.TXDX_ID)}); 

此致:

var maxes = (from x in ActiveRecordLinq.AsQueryable<table>() 
        group x by x.COLA 
        into g 
        select new {COLA = g.Key, MaxID = g.Max(z => z.ID)}); 

我仍然工作在整個查詢。試圖在一次通話中完成。一旦我得到它,我會發布,但這是星期五,我正在做這件事。

+0

我的例子中有一個非常大的錯誤 - 「WHERE COLA ='東西'GROUP BY COLA」中的分組是冗餘的。我更新了示例。基本上,WHERE應該過濾與分組不同的內容。 – Shawn 2010-09-09 17:44:49