隐藏左连接列上除第一行以外的所有数据

时间:2019-06-05 09:57:20

标签: sql join

假设我有此查询以供查看:

select a.name as Author,b.name as Book
from a
left join b on a.id = b.a_id

并产生以下输出:

Brandon Sanderson Mistborn
Brandon Sanderson Way of Kings
Brandon Sanderson Steelheart
Patrick Rothfuss  The Wise Man's Fear
Patrick Rothfuss  The Name of the Wind

到目前为止一切都很好,但我想将重复项隐藏在左行:

Brandon Sanderson Mistborn
                  Way of Kings
                  Steelheart
Patrick Rothfuss  The Wise Man's Fear
                  The Name of the Wind

这使IMO的阅读更加容易,这就是我要用于此视图的格式。

我该如何实现?

2 个答案:

答案 0 :(得分:1)

好吧,这可以通过window function来实现,如果您现在使用的数据库支持此功能,例如PostgreSQL或高版本(8.0+)的MySQL,则可以编写如下的SQL:

select * from books;
      author       |         book         
-------------------+----------------------
 Brandon Sanderson | Mistborn
 Brandon Sanderson | Way of Kings
 Brandon Sanderson | Steelheart
 Patrick Rothfuss  | The Wise Man’s Fear
 Patrick Rothfuss  | The Name of the Wind
(5 rows)

select
    case when row_number() over(partition by author order by book) > 1 then null else author end as author,
    book
from
    books;
      author       |         book         
-------------------+----------------------
 Brandon Sanderson | Mistborn
                   | Steelheart
                   | Way of Kings
 Patrick Rothfuss  | The Name of the Wind
                   | The Wise Man's Fear
(5 rows)

with tmp as (
select
    author,
    book,
    row_number() over(partition by author order by book) as sort
from
    books
)
select
    case when sort>1 then null else author end as th_author,
    book
from
    tmp
order by
    author,sort;
     th_author     |         book         
-------------------+----------------------
 Brandon Sanderson | Mistborn
                   | Steelheart
                   | Way of Kings
 Patrick Rothfuss  | The Name of the Wind
                   | The Wise Man‘s Fear

或者数据库不支持window function,您可以编写如下内容:

with named_book as (
select
    author,
    min(book) as book
from
    books
group by
    author
)
select
    b.author,
    a.book
from
    books a
left join
    named_book b on a.book = b.book
order by
    a.author,a.book;
      author       |         book         
-------------------+----------------------
 Brandon Sanderson | Mistborn
                   | Steelheart
                   | Way of Kings
 Patrick Rothfuss  | The Name of the Wind
                   | The Wise Man's Fear
(5 rows)

答案 1 :(得分:1)

这不是您通常在SQL中要做的事情。表格具有行和列,并且-通常-一行中的值sin应该独立于其他行。

您可以使用row_number()进行此操作,请注意排序标准:

select (case when 1 = row_number() over (partition by a.id order by b.name)
             then a.name
        end) as Author,
       b.name as Book
from a left join
     b
     on a.id = b.a_id
order by a.id, b.name;

外部order by键与partition byorder by子句中的键相匹配非常重要。

您可能会发现为每个作者创建一行更为有用。语法因数据库而异,但我认为标准功能是listagg()

select a.name as Author,
       listagg(b.name, '; ') within group (order by b.name) as Book
from a left join
     b
     on a.id = b.a_id
group by a.name;