самый быстрый запрос для выбора конкретной строки при использовании отличного фильтра + - PullRequest
0 голосов
/ 30 сентября 2018

Таблица ответов:

Answer ID  | User ID | Question ID | deleted
1          | 1       |  1          | f
2          | 1       |  2          | f
3          | 1       |  2          | f
4          | 1       |  1          | t
5          | 2       |  1          | f
6          | 2       |  2          | f
7          | 2       |  2          | f

Я хочу выбрать все ответы, отличные от (userID, questionID), используя самый последний ответ (на основе наибольшего идентификатора), и из этого набора результатов я хочу удалить все записи, имеющие deleted = t.

Итак, мой результат должен быть

Answer ID  | User ID | Question ID | deleted
3          | 1       |  2          | f
5          | 2       |  1          | f
7          | 2       |  2          | f

Я думаю, мы не можем сделать это с помощью сгенерированных методов запроса из интерфейса?Вместо этого я использую аннотацию @Query:

@Query("SELECT a1 FROM answer a1 WHERE ... ")
findLatestAnswers();

Я придумал это (sql fiddle: http://sqlfiddle.com/#!15/02339/8/0) и даже не использую distinct или group by или order by.Это делает работу, но кажется, что это очень неэффективно для больших наборов данных?Что было бы быстрее заявление?

SELECT * FROM answer a1
WHERE NOT EXISTS ( -- where no newer answer exists
           SELECT * FROM answer a2
           WHERE a1.user_id = a2.user_id
                   AND a1.question_id = a2.question_id
                   AND a1.id < a2.id
  )
  AND a1.deleted = FALSE;

1 Ответ

0 голосов
/ 30 сентября 2018

Нет проблем с использованием distinct или group by или функций агрегирования.Они необходимы в хранилище данных или в аналитическом программном обеспечении, где миллионы или записи обрабатываются в каждом запросе (миллиарды и триллионы в больших данных).

Единственные корректировки - это создание индексов на основе ваших данных и запросов.

Для вашего сканрио вам нужна функция max.Вы должны выбрать max из anser_id для сгруппированных user_id, question_id следующим образом:


РЕШЕНИЕ 1

@Query("select max(answer) from Answer answer where answer.deleted = false group by answer.userId, answer.questionId")
List<Answer> findLatestAnswersByUserQuestionNotDeleted();

Этот оператор возвращает 4 записи, потому что, еслиВы не рассматриваете удаленный ответ, последний ответ пользователя 1 в вопросе 1 становится 1.

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

Из-за этого вы должны постить фильтр программно удаленным, как описано вами, так что @Query становится:

@Query("select max(answer) from Answer answer group by answer.userId, answer.questionId")
List<Answer> findLatestAnswersByUserQuestion();

Опять у вас, по праву, 4 записи, потому что также удалено присутствует и должно бытьфильтруется программно


РЕШЕНИЕ 2 (два запроса из-за вашего требования игнорировать удаленное и не учитывать старый)

шаг 1 - findId ответов, включая удаленные (просто идентификатор):

@Query("select max(answer.id) from Answer answer group by answer.userId, answer.questionId")
List<Long> findLatestAnswersId();

шаг 2 - загрузка ответов по идентификатору без учета удаленных

List<Answer> findAllByDeletedIsFalseAndIdIn(List<Long> ids);

РЕШЕНИЕ 3 (один запрос)

@Query("select answer from Answer answer where answer.deleted = false and  answer.id in (select max(inAnswer.id) from Answer inAnswer)")
List<Answer> findLastestNotDeleted()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...