2016-03-30 4 views
1

Я хочу выбрать диапазон или строки из таблицы PostgreSQL. Я пробовал этот код:Выберите диапазон строк из таблицы PostgreSQL

public List<CustomersObj> list(int firstRow, int rowCount, String sortField, boolean sortAscending) throws SQLException 
     { 

      String SqlStatement = null; 

      if (ds == null) 
      { 
       throw new SQLException(); 
      } 

      Connection conn = ds.getConnection(); 
      if (conn == null) 
      { 
       throw new SQLException(); 
      } 

      int countrow = firstRow + rowCount; 
      String sortDirection = sortAscending ? "ASC" : "DESC"; 

// Oracle 
    //  SqlStatement = "SELECT A.* " 
    //   + " FROM (SELECT B.*, ROWNUM RN " 
    //   + " FROM (SELECT Y.COMPONENTSTATSID, Y.NAME, Y.SERIALNUMBER, Y.WEIGHTKG, Y.ZONECAGE, Y.POWERWATT, Y.MANIFACTURECOMPANY, Y.UFORM, " 
    //   + " Y.STATUS, Y.LOCATION, Y.HEATEMISIONSBTU, Y.PRODUCTIONENVIRONMENT, Y.STANDARTLIFETIME, Y.OPERATINGHAMIDITYRANGE, " 
    //   + " Y.OPERATINGSYSTEM, Y.DATEDEPLOYED, Y.INTERFACETYPE, Y.TYPE, Y.COOLINGCAPACITYBTU, Y.DATEADDED, Y.DESCRIPTION " 
    //   + " FROM COMPONENTWEIGHT X, COMPONENTSTATS Y WHERE X.COMPONENTSTATSID = Y.COMPONENTSTATSID AND Y.COMPONENTTYPEID = 3300 " 
    //   + " ORDER BY %S %S) B " 
    //   + " WHERE ROWNUM <= ?) A " 
    //   + " WHERE RN > ?"; 
// postgresql 
      SqlStatement = "SELECT * FROM CUSTOMERS ORDER BY %S %S offset ? limit ? "; 

      String sql = String.format(SqlStatement, sortField, sortDirection); 

      PreparedStatement ps = null; 
      ResultSet resultSet = null; 
      List<CustomersObj> resultList = new ArrayList<>(); 

      try 
      { 
       conn.setAutoCommit(false); 
       boolean committed = false; 

       ps = conn.prepareStatement(sql); 
       ps.setInt(1, countrow); 
       ps.setInt(2, firstRow); 

       resultSet = ps.executeQuery(); 
       resultList = ProcessorArrayList(resultSet); 

       conn.commit(); 
       committed = true; 

      } 
      finally 
      { 
       ps.close(); 
       conn.close(); 
      } 

      return resultList; 
     } 

Но когда я использую разбивку на страницы, я получаю разные числа или строки. Если я использую запрос из Oracle, он работает нормально. Но когда я хочу использовать запрос из PostgreSQL, я получаю разные результаты на каждой странице с разбивкой на страницы. Можете ли вы дать какой-то результат, как я могу это исправить?

ответ

1

Параметры OFFSET и LIMIT в PostgreSQL описаны в documentation как:

The LIMIT clause consists of two independent sub-clauses:

LIMIT { count | ALL } OFFSET start 

count specifies the maximum number of rows to return, while start specifies the number of rows to skip before starting to return rows. When both are specified, start rows are skipped before starting to count the count rows to be returned.

Это означает, что эта строка:

int countrow = firstRow + rowCount; 

, вероятно, неправильно. Параметр, передаваемый в LIMIT, - это фактическое количество строк, а не следующая строка.

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

  ps.setInt(1, countrow); 
      ps.setInt(2, firstRow); 

Первый из них является (плохой) «счетчик», а второй из них является «смещение». Это должно быть наоборот.

И, наконец, значение OFFSET - это количество строк для пропусков, а не номер первой строки. Поэтому, если вы ожидаете, что firstRow для первой страницы будет 1, вы должны использовать firstRow - 1 в качестве своего смещения.

Таким образом, вы должны заменить setInt линии с:

  ps.setInt(1, firstRow - 1); 
      ps.setInt(2, rowCount); 
+0

Я получаю org.postgresql.util.PSQLException: ОШИБКА: OFFSET не должно быть отрицательным –

+0

@Peter Поэтому проверьте, действительно ли 'firstRow' начинается с 1. Если он начинается с нуля, вам не нужно вычитать 1. – RealSkeptic

+0

это 1. По какой-то причине он не работает должным образом. Следующая кнопка и обратно работают неправильно. –

0

Давайте соберем воедино ключевые фразы

int countrow = firstRow + rowCount; 
SqlStatement = "SELECT * FROM CUSTOMERS ORDER BY %S %S offset ? limit ? "; 
ps = conn.prepareStatement(sql); 
ps.setInt(1, countrow); 
ps.setInt(2, firstRow); 

Аргумент LIMIT в PostgreSQL для specifiying максимальное количество строк, которые будут получены , количество строк на странице.

Аргумент OFFSET определяет, какая первая строка должна быть восстановлена.

Предположим, что вам нужно 50 строк на страницу.

To retrieve the first page -> `LIMIT 50 OFFSET 0` [rows 0 to 49] 

    To retrieve the second page -> `LIMIT 50 OFFSET 50` [rows 50 to 99] 

    ... 

    To retrieve the nth page -> `LIMIT 50 OFFSET (n - 1)*50` 

Если rowCount содержит общее количество строк для извлечения, он должен быть назначен LIMIT и ваш firstRow к OFFSET. И вы можете отменить переменную countrow, если вы используете PostgreSQL.

UPDATE: Просто измените

ps.setInt(1, firstRow); // Assign firstRow to OFFSET 
ps.setInt(2, rowCount); // Assign rowCount to LIMIT 

Боюсь, что я согласен с RealSkeptic: ", если вы ожидаете firstRow для первой страницы, чтобы быть 1, вы должны использовать firstRow - 1, как ваше смещение ," Если вы получение отрицательного числа в качестве первого аргумента, единственной причина в том, что ваши использует 0 в качестве исходного ряда.

Это имеет смысл, если учесть, что первая строка в Oracle имеет ROWNUM = 1 .

https://docs.oracle.com/cd/B14117_01/server.101/b10759/pseudocolumns008.htm

Ваш запрос действует для Oracle означает, что RN> 0 для первой страницы.

Первая строка в PostgreSQL получается с OFFSET = 0, так что ...

+0

Можете ли вы привести пример, как мне нужно реорганизовать код, потому что это не очень понятно? –

+0

@PeterPenzov Я обновил. Надеюсь яснее – RubioRic

+0

Я использую этот код http://balusc.omnifaces.org/2008/10/effective-datatable-paging-and-sorting.html Похоже, что проблема заключается в запросе. Он предназначен для этого запроса: «SELECT id, name, value FROM mydata ORDER BY% s% s LIMIT?,?"; Прямо сейчас следующая кнопка не работает нормально. После второй страницы он не работает. –

Смежные вопросы