代码之家  ›  专栏  ›  技术社区  ›  Miraj50 user2991863

Postgresql-使用distinct时保留相对位置

  •  -2
  • Miraj50 user2991863  · 技术社区  · 7 年前

    我运行了一个查询,返回了这样一个表。

     d |  e  | f  
    ---+-----+----
     2 | 103 | C
     6 | 201 | AB
     1 | 102 | B
     1 | 102 | B
     1 | 102 | B
     1 | 102 | B
     1 | 102 | B
     3 | 105 | E
     3 | 105 | E
     3 | 105 | E
    

    2 | 103 | C
    6 | 201 | AB
    1 | 102 | B
    3 | 105 | E
    

    我试过了 distinct group by ,但他们并不总是保留这个位置(他们为我的其他一些案例保留了这个位置)。任何关于如何轻松完成或需要使用其他功能的想法,如 rank ?

    3 回复  |  直到 7 年前
        1
  •  1
  •   Gordon Linoff    7 年前

    SQL表表示 无序的 order by 用一列或一个表达式。

    如果你有这样的命令,你可以用 group by :

    select d, e, f
    from t
    group by d, e, f
    order by min(a);  -- assuming a is the column that specifies the ordering
    
        2
  •  1
  •   Grant Miller    7 年前

    在下列情况下使用案例:

    order by case when f=C then 1 when f=AB then 2
    when f=B then 3 when f=E then 5 else null end
    
        3
  •  0
  •   D-Shih    7 年前

    你可以试着 order by ctid

    行版本在其表中的物理位置。请注意,虽然ctid可用于非常快速地定位行版本,但如果行的ctid是通过“真空满”更新或移动的,则该行的ctid将发生更改。因此,ctid作为长期行标识符是无用的。应该使用OID,或者更好的用户定义的序列号来标识逻辑行。

    使用 row_number 具有 ctid

    然后得到 rn = 1 order by ctid

    CREATE TABLE T(
      d int,
      e int,
      f varchar(5)
    );
    
    insert into t values (2,103, 'C');
    insert into t values (6,201, 'AB');
    insert into t values (1,102, 'B');
    insert into t values (1,102, 'B');
    insert into t values (1,102, 'B');
    insert into t values (1,102, 'B');
    insert into t values (1,102, 'B');
    insert into t values (3,105, 'E');
    insert into t values (3,105, 'E');
    insert into t values (3,105, 'E');
    

    问题1 :

    select d,e,f 
    from (
      select d,e,f,ctid,row_number() over(partition by d,e,f order by ctid) rn
      FROM T
    )t1
    where rn = 1
    order by ctid
    

    Results

    | d |   e |  f |
    |---|-----|----|
    | 2 | 103 |  C |
    | 6 | 201 | AB |
    | 1 | 102 |  B |
    | 3 | 105 |  E |