2014-10-07 57 views
2

因此,我的目標是針對特定的書籍(使用給定的編號)來獲取每種語言的發佈版本。如果沒有發佈的版本,那麼我需要通過時間戳檢索最近的版本。在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 

但是我不知道該怎麼做了類似的加入thorugh使用Hibernate的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倉庫中做這個查詢?

我不想要做一個「每個」,並獲得出版/最新的,因爲這會大大低效

這些書是設置爲

書|作者| info id

然後info id有:

infoid |語言|時間戳|狀態| .........

舉例目的是: Get 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,de的最高時間戳)

+1

GROUP BY(2個字)? – 2014-10-07 08:38:35

+0

你是否認爲會有更多的書籍具有相同的信息編號?或者同一本書會有更多的信息ID?不同的書籍記錄可以有不同的作者,它會好嗎? – peterh 2014-10-07 09:23:38

+0

嗨對不起,我不清楚 每本書都有它自己的信息ID。一位作者將有多本書。有多位作者,但是我會特別關注其中的一位。 因此,我們的目標是針對特定作者爲每本書的每種語言提取已發佈的,否則最新的。把書看作更多的修改。 – user1628284 2014-10-07 09:33:04

回答

1

不,它不好。 SQL不適用於有序集合,SQL(主要)與無序集合一起工作。這意味着,每個查詢,查詢結果,子查詢等都是一組無序的記錄。

是的,這是因爲這些套在理論上完全是你可以從高中學到的套。

如果你做了GROUP BYJOIN或任何類似的,以前的ORDER BY將被無效。爲什麼?因爲每個這樣的關鍵字都與無序集合一起工作。這也是原因,爲什麼只有最後的SQL查詢可以有ORDER BY

如果這種內部排序有效,它只是一些SQL服務器的隨機行爲(舊的mysql版本在這種解決方案中特別好奇)。

你想要的東西,是

  1. 集團,在記錄由列(publishedlanguage
  2. 該兩列訂購所需要的記錄,以及。

所以: SELECT b FROM Book b WHERE author=?1 AND info.status=published ORDER BY published, language

...或者這樣的。如果我可以破譯你想要的,可能甚至不需要group by。如果你擴展你的問題,你的目標是什麼,我將用查詢擴展我的答案。

擴展#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(hibernate查詢語言),但我很快就會做一些研究。

擴展#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 2014-10-07 09:13:48

+0

問題與我提出的在發佈和語言上進行分組的建議是,分組意味着如果兩個未發佈,則第一個將被採用,即使第二個具有更大的時間戳。這是分組前需要訂購的前述問題 – user1628284 2014-10-07 10:29:43

+0

@ user1628284不,完全不好。如果按字段進行GROUP,則可以從其他列中僅選擇GROUP-ed字段或聚合函數(f.e.「MAX()」)。只有Mysql沒有遵循這個原則,因爲他們不想讓基礎SQL初學者的生活變得更加艱難,但即使在那裏,它也是一個受損的東西。我很快給你一個工作解決方案。 – peterh 2014-10-07 10:35:17