NHibernate“SELECT ... FROM(SELECT ...”Criteria

时间:2010-09-09 12:55:41

标签: sql nhibernate criteria

我有一个SQL查询,我在创建使用NHibernate Criteria时遇到了麻烦:

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中,我可以正确地获得两个查询,但是中间的那个 - “SELECT ID FROM”将不起作用。

主要查询:

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)));

子查询标准将“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

我想要的结果是给定的一组“COLA”的最大ID,其中“COLB”匹配“某事”,所以我希望子查询返回{3,5}。最后,查询只会返回ID 3的记录(外部WHERE子句除掉5,因为COLC是错误的)。 COLB和COLC中的实际数据无关紧要 - 我只是用它来进一步过滤结果。

我认为,在它的核心,我想要每组COLA的最新记录(最大ID)

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

2 个答案:

答案 0 :(得分:2)

因此,假设您正在寻找具有最大ID和COLA值的记录,并且其中包含相应MAX ID的COLB,您可以使用类似的内容。

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))

我尝试使用我的一些对象和测试数据,它似乎工作。让我知道它是怎么回事。

修改

对于COLA的最大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)});

我还在处理整个查询。试着在一个电话中完成它。一旦我得到它,我会发布,但它是星期五,我在工作之间这样做。

答案 1 :(得分: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
}

最后,为视图创建了一个查询:

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中使用单个条件查询,但这完成了工作。