Разрешение нескольких значений, возвращаемых из запроса?

Хотя это кажется очень простой проблемой, единственное решение, которое я придумал, приведено ниже. Любые предложения для чего-то менее уродливого с меньшей временной сложностью?

Мое приложение находится на Java и извлекается с помощью базы данных MS-sql с использованием skife.jdbi.

Скажем, у меня есть Table со столбцами A, B и C, где A и B образуют первичный ключ. И я хочу получить C, особенно учитывая A и B. Это легко осуществить. Но что, если мои требования к пропускной способности очень высоки, поэтому я хочу делать эти Select операторов пакетами. Я получаю что-то вроде следующего:

Учитывая Set из Objects со значениями A и B, я перебираю список, компилируя все значения A и B. Затем я запускаю запрос типа SELECT A, B, C FROM tbl WHERE A IN :listOfAs AND B IN :listOfBs. Затем я повторяю результаты запроса, сопоставляя результат с исходным объектом, сравнивая значения A и B. Все это звучит разумно, но в итоге код выглядит так, как показано ниже, что кажется уродливым и неоптимальным?

class MyObject {

  String A;
  String B;
  String C;
  Object otherData;


  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    } else if (!(other instanceof MyObject)) {
      return false;
    } else {
      return A.equals(other.A) && B.equals(other.B);
    }
  }

  @Override
  public int hashCode() {
    return 31 * A.hashCode() + B.hashCode();
  }
}

// populates the of objects with their proper C value
void retrieveC(Set<MyObject> input) {
  Set<String> aValues = new HashSet<>();
  Set<String> bValues = new HashSet<>();

  for (MyObject object : input) {
    aValues.add(object.A);
    bValues.add(object.B);
  }

  // the dao executes the query mentioned above, and returns a Set of  
  // MyObject instances with members A, B, and C populated from the results.
  // Any results that do not contain a value for A, B, and C (which
  // shouldn't exit) are filtered out by the dao.
  Set<MyObject> results = dao.selectC(aValues, bValues);

  // ewww... O(n^2)
  for (MyObject object : input) {
    boolean resultFound = false;

    for (MyObject result : results) {
      if (object.equals(result)) {
        object.C = result.C;
        resultFound = true;
        break;
      }
    }

    if (!resultFound) {
      // handle this case
    }
  }
}

person ab11    schedule 15.12.2015    source источник


Ответы (2)


Я так понимаю, что идеальным было бы

SELECT A, B, C FROM tbl WHERE A+' '+B IN :listOfAandBs 

Это не listOfAs x listOfBs (квадратичная сложность), а listofAs . listOfBs (линейная, внутрипродуктовая)

person Joop Eggen    schedule 15.12.2015

Вместо шаблона DAO вы можете обратиться к быстрым запросам JDBI.

Таким образом, вы можете переключить пакетную обработку на потоковую. В примере, приведенном на странице JDBI, вы замените StringBuilder() на что-то, что позволит вам передавать результаты в ваш приемник один за другим по мере того, как база данных возвращает их.

Если это возможно, зависит, конечно, от вашей среды разработки.

person ahus1    schedule 16.12.2015