Sql - Select first and last record

8

I have the following tables:

CREATE TABLE tb_lote
(
  id_lote integer NOT NULL DEFAULT nextval('tb_lote_seq'::regclass),
  ds_lote character varying(255),
  CONSTRAINT pktb_lote PRIMARY KEY (id_lote)
);

CREATE TABLE tb_lote_ticket
(
  id_lote_ticket integer NOT NULL DEFAULT nextval('tb_lote_ticket_seq'::regclass),
  id_lote integer,
  nr_quantidade numeric(12,2) DEFAULT 0,
  CONSTRAINT pktb_lote_ticket PRIMARY KEY (id_lote_ticket),
  CONSTRAINT fk_tb_lote_ticket_tb_lote FOREIGN KEY (id_lote)
      REFERENCES tb_lote (id_lote) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
);

CREATE TABLE tb_processo
(
  id_processo integer NOT NULL DEFAULT nextval('tb_processo_seq'::regclass),
  id_lote_ticket integer,
  id_setor integer,
  dt_inicio timestamp without time zone,
  CONSTRAINT pktb_processo PRIMARY KEY (id_processo),
  CONSTRAINT fk_tb_processo_tb_lote_ticket FOREIGN KEY (id_lote_ticket)
      REFERENCES tb_lote_ticket (id_lote_ticket) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_tb_processo_tb_setor FOREIGN KEY (id_setor)
      REFERENCES tb_setor (id_setor) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);

And the relationship is, Each batch has N ticket and each ticket has 1 process.

- Lote    1..N   Ticket
- Ticket  1..1   Processo

I would like to know how to perform an efficient SQL to know the dt_inicio of each batch in each Setor and at the same time the " dt_final ". The dt_final would be dt_inicio of the last process.

Current Sql

SELECT 
    Lote.id_lote as "Lote.id_lote", 
    Setor.ds_setor as "Setor.ds_setor", 
    Setor.id_setor as "Setor.id_setor",
    (
        SELECT
            ProcesseTmp.dt_inicio
        FROM
            tb_processo as ProcesseTmp  
            LEFT JOIN   tb_setor as SetorTmp ON SetorTmp.id_setor = ProcesseTmp.id_setor   
            LEFT JOIN   tb_lote_ticket as LoteTicketTmp ON LoteTicketTmp.id_lote_ticket = ProcesseTmp.id_lote_ticket   
            LEFT JOIN   tb_lote as LoteTmp ON LoteTmp.id_lote = LoteOrdemTmp.id_lote  
        WHERE
            LoteTmp.id_lote = Lote.id_lote AND 
            SetorTmp.id_setor = Setor.id_setor
        ORDER BY 
            ProcesseTmp.dt_inicio
        LIMIT 1
    ) as "Processe.dt_inicio",
    (
        SELECT
            ProcesseTmp.dt_inicio
        FROM
            tb_processo as ProcesseTmp  
            LEFT JOIN   tb_setor as SetorTmp ON SetorTmp.id_setor = ProcesseTmp.id_setor   
            LEFT JOIN   tb_lote_ticket as LoteTicketTmp ON LoteTicketTmp.id_lote_ticket = ProcesseTmp.id_lote_ticket   
            LEFT JOIN   tb_lote as LoteTmp ON LoteTmp.id_lote = LoteOrdemTmp.id_lote  
        WHERE
            LoteTmp.id_lote = Lote.id_lote AND 
            SetorTmp.id_setor = Setor.id_setor
        ORDER BY 
            ProcesseTmp.dt_inicio DESC
        LIMIT 1
    ) as "Processe.dt_final",
FROM 
    tb_mapa_producao as Processe  
    LEFT JOIN tb_setor as Setor ON Setor.id_setor = Processe.id_setor   
    LEFT JOIN tb_lote_producao_ordem_ticket as LoteTicket ON LoteTicket.id_lote_ticket = Processe.id_lote_ticket   
    LEFT JOIN tb_lote_producao as Lote ON Lote.id_lote = Lote.id_lote  
WHERE 
    Processe.dt_inicio  BETWEEN '09/09/2015 00:00:00' AND '14/10/2015 23:59:59'
    and 1=1
    and ( Processe.fl_desativado is false OR Processe.fl_desativado is null )
GROUP BY 
    Lote.id_lote, 
    Setor.ds_setor, 
    Setor.id_setor, 
ORDER BY 
    Lote.id_lote, 
    Setor.ds_setor, 
    Setor.id_setor, 

Test data

tb_lote
    id_lote     |   ds_lote
    1           |   teste1
    2           |   teste2

tb_lote_ticket
    id_lote_ticket  |   id_lote     |   nr_quantidade
    1               |   1           |   10
    2               |   1           |   10
    3               |   1           |   10
    4               |   1           |   10
    5               |   1           |   10
    6               |   1           |   10
    7               |   2           |   10
    8               |   2           |   10
    9               |   2           |   10
    10              |   2           |   10

tb_processo
    id_processo     |   id_lote_ticket  |   id_setor    |   dt_inicio
    1               |   1               |   3           |   2015-10-01 15:00:00
    2               |   2               |   3           |   2015-10-01 15:12:00
    3               |   3               |   3           |   2015-10-01 15:24:00
    4               |   4               |   4           |   2015-10-01 15:36:00
    5               |   5               |   4           |   2015-10-01 15:48:00
    6               |   6               |   4           |   2015-10-01 16:00:00
    7               |   7               |   6           |   2015-10-01 15:12:00
    8               |   8               |   6           |   2015-10-01 15:24:00
    9               |   9               |   6           |   2015-10-01 15:36:00
    10              |   10              |   6           |   2015-10-01 15:48:00

Expected Result

id_lote     |   id_setor    |   dt_inicio               |   dt_final
1           |   3           |   2015-10-01 15:00:00     |   2015-10-01 15:24:00
1           |   4           |   2015-10-01 15:36:00     |   2015-10-01 16:00:00
2           |   6           |   2015-10-01 15:12:00     |   2015-10-01 15:48:00

That is: of each batch, get the start and end date of each sector, the start date corresponds to the first process in the sector and the end date corresponds to the last process in the sector .

    
asked by anonymous 02.10.2015 / 17:09

1 answer

11

There it is:

select 
    lote_ticket.id_lote, processo.id_setor, 
    min(processo.dt_inicio) as dt_inicio, max(processo.dt_inicio) as dt_final
from
    tb_processo as processo join tb_lote_ticket as lote_ticket 
        on lote_ticket.id_lote_ticket = processo.id_lote_ticket
group by
    lote_ticket.id_lote, processo.id_setor
order by 
    lote_ticket.id_lote, processo.id_setor

See the official SQL SQL Fiddle .

Explanation

You've made two subqueries that are only meant to fetch the start date and end date.

Your first subquery brings the start date by taking the first record. The second subquery is almost identical and brings the end date by grabbing the first record of the same query only in reverse order.

Well, what you did was reproduce the Min and Max aggregation functions.

My query got simpler because I used these internal bank functions instead of reproducing their behavior with subqueries.

    
08.10.2015 / 18:28