简体   繁体   English

按一对多关系排序并返回不同的记录

[英]Sorting by one-to-many relationship and return distinct records

I have a list of IDs (page__96de2231 etc.) that I want to sort by a lookup on another table (where the property = "p_published_at", also including null values).我有一个 ID 列表(page__96de2231 等),我想通过对另一个表的查找进行排序(其中属性 =“p_published_at”,还包括 null 值)。 I only want to return the IDs, properly sorted.我只想返回正确排序的 ID。 But when doing distinct on the resulting IDs the order from the inner query is lost:但是,当对结果 ID 进行区分时,内部查询的顺序会丢失:

SELECT distinct id FROM (

SELECT entity.id, t1.property, t1.postgres_timestamptz
    FROM entity
    
    JOIN triple t1
    on entity.id = t1.subject
    
    WHERE entity.id IN ('page__96de2231', 'page__1fd94de8', 'page__898f13ec', 'page__81503fa2')

    ORDER BY t1.property='p_published_at' DESC NULLS LAST, t1.postgres_timestamptz ASC NULLS LAST

) as inner_query

How can I resolve this by either improving or refactoring the query?如何通过改进或重构查询来解决这个问题?

If you want to return ids in a particular order, don't use a subquery.如果您想按特定顺序返回 id,请不要使用子查询。 You need an order by in the outer most query.您需要在最外面的查询中进行排序。

In this case, you can use group by :在这种情况下,您可以使用group by

SELECT e.id
FROM entity e JOIN     
    triple t1
    ON entity.id = t1.subject    
WHERE e.id IN ('page__96de2231', 'page__1fd94de8', 'page__898f13ec', 'page__81503fa2')
GROUP BY e.id
ORDER BY COUNT(*) FILTER (WHERE t1.property = 'p_published_at') DESC NULLS LAST,
         MAX(t1.postgres_timestamptz) ASC NULLS LAST;

By the way, you don't need a JOIN for this either:顺便说一句,您也不需要JOIN

SELECT t1.subject as id
FROM triple t1
WHERE t1.subject IN ('page__96de2231', 'page__1fd94de8', 'page__898f13ec', 'page__81503fa2')
GROUP BY t1.subject
ORDER BY COUNT(*) FILTER (WHERE t1.property = 'p_published_at') DESC NULLS LAST,
         MAX(t1.postgres_timestamptz) ASC NULLS LAST

One entity can have many triples.一个实体可以有多个三元组。 If an entity has two triples, one sorted at the beginning of the list, one at the end of it, where would you place the entity in your results?如果一个实体有两个三元组,一个在列表的开头排序,一个在列表的末尾,您会将实体放在结果中的什么位置? At the beginning or the end?在开始还是结束?

You can use DENSE_RANK to give the rows sortkeys.您可以使用DENSE_RANK给行排序键。 Then decide whether to take the minimum or maximum sortkey per entity:然后决定是否对每个实体采用最小或最大排序键:

select id
from
(
  select
    e.id,
    dense_rank() over (order by t.property = 'p_published_at' desc nulls last,
                                t.postgres_timestamptz asc nulls last) as sortkey
  from entity e
  join triple t on e.id = t.subject
  where e.id in ('page__96de2231', 'page__1fd94de8', 'page__898f13ec', 'page__81503fa2')
) ranked
group by id
order by min(sortkey), id;

(And Gordon is right of course, you can remove the table entity from the query; it is not needed.) (当然 Gordon 是对的,您可以从查询中删除表实体;这不是必需的。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM