Mixed ordering by date and by type

Обновить

December 2018

Просмотры

44 раз

1

Так скажем, у меня есть база данных, которая выглядит следующим образом

Posts
id | author_id | created_at
 1           1    1.day.ago
 2           1    2.day.ago
 3           2    3.day.ago
 4           1    4.day.ago

Authors
id | type
 1   Male
 2   Female

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

Так что, если я только что сделал:

Post.order('created_at desc')

Я бы получил:

Posts
id | author_id | created_at
 1           1    1.day.ago
 2           1    2.day.ago
 3           2    3.day.ago
 4           1    4.day.ago

Но, допустим, вместо этого я хочу, чтобы результаты были в таком порядке:

Posts
id | author_id | created_at
 1           1    1.day.ago
 3           2    3.day.ago
 2           1    2.day.ago
 4           1    4.day.ago

Так что я получаю первый самый последний пост от автора 1, то самый последний пост от автора 2, даже если это старше, чем на следующий пост от автора 1, то, так как нет больше сообщений от автора 2, она возвращает остаток в обычном порядке created_at.

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

Возможно ли это сделать в SQL Server?

3 ответы

1

You can order by a custom order using something like:

ORDER BY ROW_NUMBER()OVER(PARTITION BY author_id ORDER BY created_at DESC)
,        author_id

If you add it to the select, you can see the result more easy, and apply tweaks where necessary.

At least, this is allowed in sql server, I assume likewise for postgreSQL.

1

Если я правильно понимаю, один способ:

with Posts(id , author_id , created_at) as(
select 1       ,    1    ,'2017-09-17'::date union all
select 2       ,    1    ,'2017-09-16'::date union all
select 3       ,    2    ,'2017-09-15'::date union all
select 5       ,    2    ,'2017-09-10'::date union all
select 4       ,    1    ,'2017-09-14'::date  
)

select * from (
    select * ,row_number() over(partition by author_id order by created_at desc) as rn  
    from Posts
) t
order by rn, created_at desc
1

We can assign a row number across a partition on authors, with the most recent posts being assigned the lowest row numbers. Then order by this row number, followed by the author id to break the tie.

select
    t.id,
    t.author_id,
    t.created_at
from
(
    select id, author_id, created_at,
        row_number() over (partition by author_id order by created_at desc) rn
    from Posts
) t
order by
    t.rn,
    t.author_id