Как можно сделать запрос Oracle Top-N (Chasted) в дозвуковой 2.2?

StackOverflow https://stackoverflow.com/questions/3824483

Вопрос

(Отказ от ответственности: Я поменял / запустил некоторые из имени переменных / таблиц / столбцов здесь по соображениям безопасности. Пожалуйста, прости меня, если что-то выглядит немного.)

Я строю вторжение в базу данных Oracle 10G, и я пытаюсь получить данные построили. Помимо пейджинга, следующий подгрунительный код 2.2 дает мне то, что я хочу, в порядке, я хочу это:

var q = new Select()
  .From(AppDb.MyTable.Schema)
  .Where(AppDb.MyTable.DisabledDateColumn).IsNull()
  .OrderDesc(AppDb.MyTable.CreatedDateColumn.ColumnName)

System.Console.Out.Writeline(q.BuildStatement());

Это дает следующий SQL:

SELECT
    MYSCHEMA.MYTABLE.ID,
    MYSCHEMA.MYTABLE.DISABLED_DATE
FROM
    MYSCHEMA.MYTABLE
WHERE
    MYSCHEMA.MYTABLE.DISABLED_DATE IS NULL
ORDER BY
    CREATED_DATE DESC

Затем я пытаюсь представить пейджинг:

var q = new Select()
  .From(AppDb.MyTable.Schema)
  .Where(AppDb.MyTable.DisabledDateColumn).IsNull()
  .OrderDesc(AppDb.MyTable.CreatedDateColumn.ColumnName)
  .Paged(0, 10);

И он вытирает мой, где и порядок по пунктам:

SELECT * FROM (
    SELECT
        MYSCHEMA.MYTABLE.ID,
        MYSCHEMA.MYTABLE.DISABLED_DATE,
        ROWNUM as row_number
    FROM
        MYSCHEMA.MYTABLE
)
WHERE
    row_number BETWEEN 1 AND 10

Я совершенно новой для дозвуковой, поэтому я не знаю, если это ошибка, или я просто не делаю это предпочтительным образом, или если Oracle требует, чтобы это было сделано в другом, более ориентированном на оракул. (Oracle, кажется, требует всего во всем.)

Что я хочу, на случай, если это не очевидно, каждая преуспевающая страница включает 10 следующих последних, созданных неразъемных записей. Как я могу сделать это в дозвуковой 2.2?

Это было полезно?

Решение

Похоже, ваш запрос не генерирует тот же SQL, что и текущий Oracle поставщик данных для дозвуковых должен. Вот соответствующий код (начиная с строки 852):

    if(qry.PageIndex < 0)
        query = String.Format("{0} {1} FROM {2}.{3} {4} {5}",select ,columns, table.SchemaName, table.Name, where, order);
    else
    {
        int start = qry.PageIndex * qry.PageSize;
        int end = (qry.PageIndex + 1) * qry.PageSize;

        const string cteFormat =
                    "WITH pagedtable AS (SELECT {0}, ROW_NUMBER () OVER ({1}) AS rowindex FROM {2}.{3} {4}) SELECT {5}, rowindex FROM pagedtable WHERE rowindex >= {6} AND rowindex < {7} ORDER BY rowindex";
        query = string.Format(cteFormat, columns, order,table.SchemaName, table.Name, where, columns.Replace(table.Name + ".", String.Empty), start, end);
    }
    return query;

Возможно, обновление к источнику тока будет делать трюк. Если что-то не так с фактическим провайдером, вы можете сравнить его с SqldataProvider для подсказки относительно того, что может быть проблемой.

Другие советы

Я в среде, используя Net 2.0 и Oracle 9i R2, и я столкнулся с той же точной проблемой. Я использую дозвуковую 2.2.

Я скачал источник из Github, и это то, что я нашел:

Код, указанный @Ranomore (oracledatataProvider.getselectsql ()), называется только при использовании объекта Subsonic.Query. Поскольку OP и я используют объект SELECT, который получен из более нового и более мощного объекта Subsonic.sqlquery, oracledataProvider.getselectsql () никогда не вызывается. Вместо, OracleGenerator.BuildPagedSelectedStement () Вызывается и генерирует SQL, вы видите, опубликованные ОП. Этот код BUGGY, так как он никогда не добавляет, где и порядок по пунктам Pagination его в конечном итоге генерирует.

Я заменил содержимое BuildPagedSelectementStement () с чем-то на основе ANSISQLGENERATOR.BUILDSELECTSTSTEMENT ():

public override string BuildPagedSelectStatement()
{
    int startnum = query.PageSize * query.CurrentPage + 1;
    int endnum = query.PageSize * query.CurrentPage + query.PageSize;
    string orderBy = String.Empty;

    if (this.query.OrderBys.Count > 0)
        orderBy = GenerateOrderBy();

    //The ROW_NUMBER() function in Oracle requires an ORDER BY clause.
    //In case one is not specified, we need to halt and inform the caller.
    if(orderBy.Equals(String.Empty))
        throw new ArgumentException("There is no column specified for the ORDER BY clause", "OrderBys");

    System.Text.StringBuilder sql = new System.Text.StringBuilder();

    //Build the command string
    sql.Append("WITH pagedtable AS (");
    sql.Append(GenerateCommandLine());

    //Since this class is for Oracle-specific SQL, we can add a hint
    //which should help pagination queries return rows more quickly.
    //AFAIK, this is only valid for Oracle 9i or newer.
    sql.Replace("SELECT", "SELECT /*+ first_rows('" + query.PageSize + "') */");

    sql.Append(", ROW_NUMBER () OVER (");
    sql.Append(orderBy);
    sql.Append(") AS rowindex ");
    sql.Append(Environment.NewLine);
    sql.Append(GenerateFromList());
    sql.Append(GenerateJoins());

    sql.Append(GenerateWhere());

    if (query.Aggregates.Count > 0)
    {
        sql.Append(GenerateGroupBy());
        sql.Append(Environment.NewLine);
        sql.Append(GenerateHaving());
    }

    sql.Append(") SELECT * FROM pagedtable WHERE rowindex >= ");
    sql.Append(startnum);
    sql.Append(" AND rowindex < ");
    sql.Append(endnum);
    sql.Append(" ORDER BY rowindex");

    return sql.ToString();
}

Выше сработало для меня. Надеюсь, это поможет другим!

Oracle будет в порядке с помощью Top-n Query, если внутренний SQL будет состоять из первого утверждения (в том числе и порядка).

Итак, я бы сказал, что нет особой причины оракула, чтобы их опустить.

Никогда не использовал подгруппу, не знаю, если вам нужно сделать это отличаться там.

Performance Wise, индекс на disadov_date, create_date должен сделать трюк (см.: http://blog.fatalmind.com/2010/07/30/analytic-top-n-queries/).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top