7

我需要从标准查询中获取行数,并且标准按投影分组。(需要让寻呼工作)

例如

projectionList.Add(Projections.GroupProperty("Col1"), "col1")
              .Add(Projections.CountDistinct("Col2"), "Count");

我需要避免使用 CreateSQL,因为我有很多标准……而且限制等很复杂。

你能做一个子标准(分离)然后select count(*) from ..?想不通怎么办?

编辑:我通过从条件中获取 sql 然后对其进行修改以使其现在可以工作来解决它!GetSql 从标准

4

4 回答 4

0

不完全确定你想要什么,但这样的事情应该有效(如果我正确理解你的问题):

var subQuery = DetachedCriteria.For<SomeClass>()
   .Where(... add your conditions here ...);

var count = Session.CreateCriteria<SomeClass>()
   .Where(Property.ForName("Col1").In(
      CriteriaTransformer.Clone(subQuery).SetProjection(Projections.Property("Col1"))
   .SetProjection(Projections.Count())
   .FutureValue<int>();

var results = subQuery.GetExecutableCriteria(Session)
            .SetProjection(Projections.GroupProperty("Col1"), "col1"),
                           Projections.CountDistinct("Col2"), "Count")
            ).List<object[]>();
于 2012-05-21T12:06:37.983 回答
0

我已经在 java 版本(Hibernate)上解决了这个问题。问题是 RowProjection 函数有点像:

count(*) 

这是一个聚合函数:因此,如果您创建一个“分组依据”属性,您的结果是分组行的列表,并且对于每一行,您都有该组的总数。

对我来说,使用 oracle 数据库,为了使其工作,我创建了一个自定义投影,而不是创建函数 count(*),函数是

count(count(*)) 

并且 group by 子句中的属性没有写在 select ... from 语句中。要做到这一点并不那么简单,问题是您必须提供所有堆栈来创建正确的 sql,所以,我必须使用 java 版本来子类化 2 类:SimpleProjection ProjectionList

之后我的查询生成为:

select count(*), col1, col2 from table1 group by col1, col2

变得

select count(count(*)) from table1 group by col1, col2

结果是由给出的总行

select col1, col2 from table1 group by col1, col2

(可与分页系统一起使用)

如果对您有用,我在这里发布类的 java 版本:

public class CustomProjectionList extends ProjectionList {

    private static final long serialVersionUID = 5762155180392132152L;


    @Override
    public ProjectionList create() {
        return new CustomProjectionList();
    }

    public static ProjectionList getNewCustomProjectionList() {
        return new CustomProjectionList();
    }

    @Override
    public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < getLength(); i++) {
            Projection proj = getProjection(i);
            String sqlString = proj.toSqlString(criteria, loc, criteriaQuery);
            buf.append(sqlString);
            loc += getColumnAliases(loc, criteria, criteriaQuery, proj).length;
            if (i < (getLength() - 1) && sqlString != null && sqlString.length() > 0)
                buf.append(", ");
        }
        return buf.toString();
    }

    private static String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
        return projection instanceof EnhancedProjection ?
                ( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) :
                projection.getColumnAliases( loc );
    }


}

public class CustomPropertyProjection extends SimpleProjection {


    private static final long serialVersionUID = -5206671448535977079L;

    private String propertyName;
    private boolean grouped;


    @Override
    public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
        return new String[0];
    }

    @Override
    public String[] getColumnAliases(int loc) {
        return new String[0];
    }

    @Override
    public int getColumnCount(Criteria criteria, CriteriaQuery criteriaQuery) {
        return 0;
    }


    @Override
    public String[] getAliases() {
        return new String[0];
    }

    public CustomPropertyProjection(String prop, boolean grouped) {
        this.propertyName = prop;
        this.grouped = grouped;
    }

    protected CustomPropertyProjection(String prop) {
        this(prop, false);
    }

    public String getPropertyName() {
        return propertyName;
    }

    public String toString() {
        return propertyName;
    }

    public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
    throws HibernateException {
        return new Type[0];
    }

    public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) 
    throws HibernateException {

        return "";
    }

    public boolean isGrouped() {
        return grouped;
    }

    public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) 
    throws HibernateException {
        if (!grouped) {
            return super.toGroupSqlString(criteria, criteriaQuery);
        }
        else {
            return StringHelper.join( ", ", criteriaQuery.getColumns( propertyName, criteria ) );
        }
    }

}

public class CustomRowCountProjection extends SimpleProjection {
    /**
     * 
     */
    private static final long serialVersionUID = -7886296860233977609L;


    @SuppressWarnings("rawtypes")
    private static List ARGS = java.util.Collections.singletonList( "*" );

    public CustomRowCountProjection() {
        super();
    }


    public String toString() {
        return "count(count(*))";
    }

    public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        return new Type[] {
                getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() )
        };
    }

    public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
        SQLFunction countSql = getFunction( criteriaQuery );
        String sqlString = countSql.toString() + "(" +  countSql.render( null, ARGS, criteriaQuery.getFactory() ) + ") as y" + position + '_';
        return sqlString;
    }

    protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
        SQLFunction function = criteriaQuery.getFactory()
                .getSqlFunctionRegistry()
                .findSQLFunction( "count" );
        if ( function == null ) {
            throw new HibernateException( "Unable to locate count function mapping" );
        }
        return function;
    }
}

希望这有帮助。

于 2012-05-21T16:11:55.107 回答
0

只是跳出框框思考一下,并从 NIBerate 中删除查询复杂性。您可以在数据库中为查询创建一个视图,然后为该视图创建一个映射。

于 2012-05-21T13:43:21.863 回答
0

我认为这可以通过使用 NH 多查询来完成。

这里有一些关于它的东西:http: //ayende.com/blog/3979/nhibernate-futures示例展示了我们如何在到数据库的一次往返中运行查询并获取该查询的结果计数。

这是一个很好的答案,这听起来与您想要实现的目标相似:nhibernate 2.0 Efficient Data Paging DataList Control 和 ObjectDataSource,它们在其中获得结果页面和一次往返数据库的总记录数。

另外,我怀疑是否可以在@@rowcount不更改 sql 查询的情况下使用 NH 读取纯值,就像@@rowcount数据库特定的东西一样。

我的假设是,对于您的情况,除非您简化查询或方法,否则无法从标准解决方案中避免 GetSql 。也许也值得一试。

如果您可以发布更大的代码块,那么可能有人能够解决这个问题。

于 2012-05-15T21:50:22.373 回答