2014-10-07 1 views
2

Итак, моя цель - создать определенную книгу (с данным идентификатором), чтобы получить опубликованную версию для каждого языка. Если нет опубликованной версии, мне нужно получить самую последнюю по метке времени.Order By Before Group By в JPA Spring Repository

Мне нужно сделать запрос, посредством которого заказ выполняется перед группой.

Я знаю, что в SQL вы можете сделать (примерно)

Select * From 
(Select b from Book as b where b.author = ?1 ORDER BY (case when b.info.status=published then 1 else 2) asc, b.timestamp desc) 
GroupBy book.language 

Однако я не знаю, как сделать подобный присоединиться Копание запрос в JPA хранилище с помощью спящего режима. Я знаю, что это не работает, так как порядок теряется из-за «в»

Select a From book a where a.id in 
(Select b from Book as b where b.author=?1 ORDER BY (case when b.info.status=published then 1 else 2) asc, b.timestamp desc) 
GroupBy a.language 

Как проходит и проверки в, это означает, что порядок не соблюдается. Есть ли способ сделать этот запрос в репозитории jpa?

Я не хочу, чтобы сделать «для каждого» и получить изданную/последнее, так как это будет очень неэффективно

книги установлены как

книги | автор | Информация ID

Тогда информация идентификатор:

infoid | язык | временная метка | статус 0 .........

Пример Целью было бы: Получить j.k. rowlings опубликованы/последнее в каждом языке

Пример настройка книги будет

book | author | info id 
1 |Rowling |1 
2 |Rowling |2 
3 |Rowling |3 
4 |Rowling |4 
5 |Tolkein |5 

информация:

id|lang|ts | status 
1 |en |1 | published 
2 |de |5 | unpublished 
3 |de |3 | unpublished 
4 |en |9 | unpublished 
5 |en |4 | published 

запрашивающего это woudl вернуть книгу 1 (как опубликовано и на английском языке), и 2 (как в de, с наивысшей отметкой времени)

+1

ГРУППА BY (2 слова)? –

+0

Вы думаете, что будет больше книг с одинаковым идентификатором информации? Или будет больше идентификатора информации с той же книгой? В разных книжных записях могут быть разные авторы, будет ли это нормально? – peterh

+0

Привет Прошу прощения за то, что вы не поняли Каждая книга будет иметь свой собственный идентификатор. У одного автора будет несколько книг. Есть несколько авторов, однако я буду заинтересован в этом, в частности. Поэтому целью является получение опубликованного, в противном случае последнего, для каждого языка каждой книги для конкретного автора. Подумайте о книгах как о дополнительных изменениях. – user1628284

ответ

1

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

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

Если вы делаете GROUP BY, то JOIN, или любые аналогичные, предыдущие ORDER BY будут признаны недействительными. Зачем? Потому что все такие ключевые слова работают с неупорядоченными наборами. Это также причина, почему только последний SQL-запрос может иметь ORDER BY.

Если каким-то образом это внутреннее упорядочение работает, это всего лишь случайное поведение некоторых SQL-серверов (старые версии mysql были особенно интересны в таких решениях).

То, что вы хотели, это

  1. GROUP в записях по два колонн (published и language)
  2. ЗАКАЗУ необходимые записи по этим двум колонкам, а также.

Итак: SELECT b FROM Book b WHERE author=?1 AND info.status=published ORDER BY published, language

... или такой. Если бы я мог расшифровать то, что вам нужно, возможно, даже group by были не нужны. Если вы продолжите свой вопрос, какова ваша цель, я продолжу свой ответ с запросом.

Extension # 1:

Это не может быть сделано с основным SQL, который она требует оконных функций. Запрос SQL, который делает то, что вы хотите:

SELECT *, ROW_NUMBER() OVER (ts PARTITION BY author, lang ORDER BY ts) AS tsn FROM Book b LEFT JOIN info i ON b.info_id=i.id WHERE tsn=1

В любом случае, вы должны искать функции ROW_NUMBER() SQL, и, вероятно, вам не нужно будет GROUP BY.

У меня нет никакой подсказки, как его можно портировать на hql (язык спящего языка), но я немного поработаю над этим исследованием.

Расширение # 2:

Mysql не имеют функции оконной или что-нибудь, который сделал SQL полезным. В древности это было потому, что у них не было достаточно программиста и нужна быстрая система, а не умная. В настоящее время это связано с тем, что mysql принадлежит Oracle, и они не будут свободно конкурировать с их SQL-сервером. В любом случае, mysql плох, и в долгосрочной перспективе, особенно если вы достаточно хороши для java, я предлагаю вам использовать некоторые лучшие DB (с postgresql вы действительно были довольны, я думаю).

До тех пор, вот SQL-решение. Это немного сложнее. Во-первых, мы получаем максимальную временную метку для каждого автора, книги и языка:

SELECT book.author, book.id as book_id, info.lang, MAX(info.ts) AS ts FROM book LEFT JOIN info ON book.info_id=info.id GROUP BY book.author, book.id, info.lang

Мы называем этот запрос в качестве $queryMaxts. Попробуйте этот запрос, он должен работать.

После этого, мы можем присоединиться к этому вернуться к таблицам, которые мы хотим:

SELECT * FROM ($queryMaxts) maxts LEFT JOIN book ON maxts.author=book.author LEFT JOIN info ON maxts.lang=info.lang AND maxts.ts=info.ts AND book.info_id=info.id

... хотя это чистое решение Msql и не имеет никакого отношения к JPA делать. Я предлагаю внедрить это в слой JPA.

Еще одна важная вещь:

Вы почти уверены, что временные метки являются уникальными. Вы можете гарантировать это, что также ускорило вашу базу данных, создав уникальный индекс: CREATE UNIQUE INDEX uniqts ON info(lang, ts).

+0

Спасибо за ваш ответ. Я обновил свой ответ с дополнительной информацией. Глядя на ваше сообщение Это может сработать, сгруппировавшись по опубликованному и языку, отсортированным по языку Это значительно сократит число, где может быть осуществлено в java для циклического прохождения и просто отслеживать, если язык уже используется. – user1628284

+0

Проблема С тем, что я предложил для группировки на опубликованных и языках, заключается в том, что группировка означает, что если два не опубликованы, то первый будет выполнен, даже если второй имеет более высокую временную метку. Это проблема, о которой нужно заявить, прежде чем группировать – user1628284

+0

@ user1628284 Нет, это абсолютно плохо. Если вы GROUP по полю, вы можете выбрать только поле GROUP-ed или агрегированные функции (например, «MAX()») из любых других столбцов. Только Mysql не следует за этим, потому что они не хотят усложнять жизнь для базовых новичков SQL, но это даже поврежденная вещь. Я дам вам рабочее решение в ближайшее время. – peterh