仅使用PostgreSQL加入关联表的最后一行

时间:2014-02-06 13:14:49

标签: sql postgresql

鉴于以下表格:

Table "public.vs_protocolo"
     Column      |            Type             |                         Modifiers                         
-----------------+-----------------------------+-----------------------------------------------------------
 id              | integer                     | not null default nextval('vs_protocolo_id_seq'::regclass)
 data_criacao    | timestamp without time zone | not null default now()
 ano_processo    | integer                     | not null
 numero_processo | integer                     | not null


Table "public.vs_protocolo_historico"
    Column    |            Type             |                              Modifiers                              
--------------+-----------------------------+---------------------------------------------------------------------
 id           | integer                     | not null default nextval('vs_protocolo_historico_id_seq'::regclass)
 id_protocolo | integer                     | not null
 descricao    | character varying(255)      | not null
 status       | integer                     | not null default 0
 data_criacao | timestamp without time zone | not null default now()

我必须选择与vs_protocolo中最后一行连接的vs_protocolo_historico中的所有行。

我担心性能,所以它必须避免子查询,或者至少避免vs_protocolo的每一行的子查询。

注意:vs_protocolo_historico(id_protocolo) REFERENCES vs_protocolo(id)

2 个答案:

答案 0 :(得分:2)

我认为这个更简单,更快

select
    id,
    p.ano_processo,
    p.numero_processo,
    h.descricao,
    h.status,
    h.data_modificacao
from
    vs_protocolo p
    inner join
    (
        select distinct on (id_protocolo)
            id_protocolo as id,
            descricao,
            status,
            data_criacao as data_modificacao
        from vs_protocolo_historico
        order by id_protocolo, data_criacao desc
    ) h using (id)

答案 1 :(得分:0)

这是对案例最简单的查询。不确定数千行是否仍然很快。

SELECT 
    p.id,
    p.ano_processo,
    p.numero_processo,
    h.descricao,
    h.status,
    h.data_criacao AS data_modificacao
FROM vs_protocolo p
INNER JOIN vs_protocolo_historico h
    ON h.id_protocolo = p.id
    AND h.data_criacao = (
        SELECT data_criacao
        FROM vs_protocolo_historico
        WHERE id_protocolo = p.id
        ORDER BY data_criacao DESC
        LIMIT 1
    );

这是它的查询计划。

QUERY PLAN                                         
-------------------------------------------------------------------------------------------
 Hash Join  (cost=40.75..3161.13 rows=2 width=173)
   Hash Cond: ((h.id_protocolo = p.id) AND (h.data_criacao = (subplan)))
   ->  Seq Scan on vs_protocolo_historico h  (cost=0.00..14.10 rows=410 width=161)
   ->  Hash  (cost=22.30..22.30 rows=1230 width=16)
         ->  Seq Scan on vs_protocolo p  (cost=0.00..22.30 rows=1230 width=16)
   SubPlan
     ->  Limit  (cost=15.13..15.14 rows=1 width=8)
           ->  Sort  (cost=15.13..15.14 rows=2 width=8)
                 Sort Key: vs_protocolo_historico.data_criacao
                 ->  Seq Scan on vs_protocolo_historico  (cost=0.00..15.12 rows=2 width=8)
                       Filter: (id_protocolo = $0)