SQL在行之间有条件地删除

时间:2017-11-14 10:31:10

标签: sql postgresql

我有一个包含多行的表用于相同的ID,我只需要保留一行符合以下规则:

  • NUM ='AM'优先于其他
  • 如果多个NUM ='AM'或无,则以最早的日期为准

例如:

|_ID_|_NUM_|______DATE______|
| 99 | AM  |   2015-04-12   |
| 99 | QS  |   2012-05-31   |
| 99 | AM  |   2013-02-18   | 

我需要保留最后一行。

|_ID_|_NUM_|______DATE______|
| 99 | QS  |   2013-05-31   |
| 99 | QS  |   2016-02-18   |  

我需要保留第一行。

我在postgres数据库中,我不能使用函数或过程 谢谢你的帮助。

3 个答案:

答案 0 :(得分:2)

distinct on。真假之前的错误命令。

import java.io.Serializable;
import java.math.BigInteger;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import digifred.model.global.Entidades;
import digifred.model.global.IdentidadesGenero;
import digifred.model.global.OrientacoesSexuais;
import digifred.model.global.Pessoas;


@Entity
@Table(name = "pacientes", schema = "sau")
public class Pacientes implements Serializable  {



    private static final long serialVersionUID = 5776384003601026304L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "idPaciente")
    private Long idPaciente;


    @JoinColumn(name="id_entidade")
    @ManyToOne(cascade = CascadeType.ALL)
    private Entidades entidade;


    @Basic(optional = false)
    @JoinColumn(name="idPessoa")
    @ManyToOne(cascade = CascadeType.ALL)
    private Pessoas pessoa;


    @Column(name = "idResponsavel_familiar")
    private BigInteger responsavelFamiliar;


    @Column(name = "nomeResponsavel")
    private String nomeResponsavel;


    @Column(name = "cpfResponsavel")
    private String cpfResponsavel;


    @Column(name = "cnsResponsavel")
    private String cnsResponsavel;


    @Column(name = "flagAlergico")
    private Integer flagAlergico;


    @Column(name = "observacoesAlergias")
    private String observacoesAlergias;


    @Column(name = "microarea")
    private String microarea;


    @Column(name = "idDomicilio")
    private Long idDomicilio;


    @JoinColumn(name="idOrientacaoSexual")
    @ManyToOne
    private OrientacoesSexuais orientacaoSexual;


    @JoinColumn(name="idIdentidadeGenero", insertable=false, updatable=false)
    @ManyToOne
    private IdentidadesGenero identidadeGenero;


    @Basic(optional = false)
    @Column(name = "flag_ativo")
    private int flagAtivo;


    @JoinColumn(name="idArea")
    @ManyToOne
    private Areas area;


    @JoinColumn(name="idFamilia")
    @ManyToOne
    private Familias familia;

    public Pacientes() {
    }


 getters and setters
}

答案 1 :(得分:1)

您的输出数据与示例数据不对应,因此我假设您要保留一行num = 'AM'minimum datemin date num <> 'AM'每个id并删除所有其他行,因此可以采用一种方式。

WITH cte
AS (
    SELECT t.*
        ,row_number() OVER (
            PARTITION BY id
             ORDER BY (case when num = 'AM' then 1 else 2 end)
                ,DATE asc
            ) AS rn
    FROM table1 t
    )
DELETE
FROM table1 t1
WHERE EXISTS (
        SELECT 1
        FROM cte c
        WHERE t1.num = c.num
            AND t1.DATE = c.DATE
            AND t1.num = c.num
            AND c.rn <> 1
        );

<强>结果:

id  num    date
------------------------------
99  AM     18.02.2013 00:00:00

<强> DEMO

答案 2 :(得分:0)

如果我理解你的问题,我认为这就是你所寻求的:

with cte as (
  select
    id, num, date,
    row_number() over (partition by id order by num = 'AM' desc, date) as rn
  from foo
)
select
  id, num, date
from cte
where rn = 1