Java SQL非重复多列
我有如下表格:Java SQL非重复多列,java,sql,postgresql,greatest-n-per-group,Java,Sql,Postgresql,Greatest N Per Group,我有如下表格: book_id author_id mark year 1 1 BAD 2014 1 1 MEDIUM 2014 1 1 GREAT 2015 我想执行一个查询,为每个作者提供最好的书。 大概是这样的: book_id author_id mark year 1 1
book_id author_id mark year
1 1 BAD 2014
1 1 MEDIUM 2014
1 1 GREAT 2015
我想执行一个查询,为每个作者提供最好的书。
大概是这样的:
book_id author_id mark year
1 1 GREAT 2015
我尝试在多个字段上使用distinct关键字,但当我这样做时:
select distinct book_id, author_id from Books
我只得到了书号和作者号(正如预期的那样)——但我还需要标记和年份——但我无法将其添加到不同的短语中
目前我正在使用Postgres9.4,但我需要一个ANSI-SQL解决方案
有办法吗?通常使用窗口函数解决问题:
select *
from (
select book_id, author_id, mark, year,
row_number() over (partition by author_id order by case mark when 'GREAT' then 1 when 'MEDIUM' then 2 else 3 end) as rn
from books
) t
where rn = 1;
以上是标准的ANSI SQL,但在Postgres中使用(专有的)distinct on
通常要快得多:
select distinct on (author_id) book_id, author_id, mark, year,
from books
order by author_id,
case mark when 'GREAT' then 1 when 'MEDIUM' then 2 else 3 end
如果一本书有几行,如何选择标记和年份,即返回的行?(最佳标记,或最近一年?如果两行标记相同但年份不同,或相同年份但标记不同…)在这种情况下,我们需要最佳标记您是否需要按
作者id
和图书id
进行分区?@matt:Noam希望每个作者都有最好的书。如果按作者和图书id进行划分,则每本书的每个作者都会得到最好的分数。例如,如果一个作者有两本书,那么按作者和书进行分区将返回两本书,而不仅仅是一本。@a_horse_和_no_名称,当我使用Postgres时,您的两种解决方案似乎都非常有效,但当我尝试为其编写测试时(使用内存H2)我为'distinct on'解决方案得到了这个异常:org.h2.jdbc.JdbcSQLException:SQL语句中的语法错误。。。应为“*,不存在,相交,选择,从”“分区”解决方案的代码>和此代码:org.h2.jdbc.JdbcSQLException:SQL语句中的语法错误。。。预期“)”代码>刚刚在这里看到--目前H2中没有对窗口函数的支持。。。所以我需要另一个解决方案,因为我所有的测试都在内存中使用H2。@Noam:你要求的是ANSI SQL解决方案。你从来没有提到你需要这个来做H2。这是另一个很好的例子,说明为什么在测试和生产中使用不同的DBMS是个坏主意。使用标签查看MySQL的答案。由于MySQL不支持这两种方法,您可能会在那里得到一些答案。但是要准备好,任何其他解决方案在使用真实数据时都会慢得多(尤其是比distinct on()
更慢)