PostgreSQL, drag and swap

后端 未结 2 965
滥情空心
滥情空心 2021-01-26 12:55

I have successfully solved situation regarding swapping rows by value here what still work excellent.
But by using this function I see some lacks of functionality in mean of

2条回答
  •  忘掉有多难
    2021-01-26 13:18

    Example 1:

    update kalksad1 set brred=_brred
    from (
      select
        row_number() over (
          order by brred<2 desc, brred=4 desc, brred>=2 desc, brred
        ) as _brred,
        kalk_id as _kalk_id
      from kalksad1
      where brkalk=2
      order by _kalk_id
    ) as _
    where kalk_id=_kalk_id and brred!=_brred;
    

    Example 2:

    update kalksad1 set brred=_brred
    from (
      select
        row_number() over (
          order by brred<4 desc, brred!=1 desc, brred>=4 desc, brred
        ) as _brred,
        kalk_id as _kalk_id
      from kalksad1
      where brkalk=2
      order by _kalk_id
    ) as _
    where kalk_id=_kalk_id and brred!=_brred;
    

    If you have unique index on (brkalk,brred) then it would be more complicated, as during renumbering there'll be duplicate brred.


    But for many rows I'd recommend using something which was very useful in the days of BASIC language on 8bit computers - number your rows with gaps.

    So instead of:

    (26, 2, 1, 'text index 26 doc 2 row 1'),
    (30, 2, 2, 'text index 30 doc 2 row 2'),
    (42, 2, 3, 'text index 42 doc 2 row 3'),
    (43, 2, 4, 'text index 43 doc 2 row 4'),
    (12, 2, 5, 'text index 12 doc 2 row 5'),
    

    use:

    (26, 2, 1024, 'text index 26 doc 2 row 1'),
    (30, 2, 2048, 'text index 30 doc 2 row 2'),
    (42, 2, 3072, 'text index 42 doc 2 row 3'),
    (43, 2, 4096, 'text index 43 doc 2 row 4'),
    (12, 2, 5120, 'text index 12 doc 2 row 5'),
    

    Then your examples would just look like:

  • Example 1: update kalksad1 set brred=(2048+1024)/2 where kalk_id=43, which would change it to:

    (26, 2, 1024, 'text index 26 doc 2 row 1'),
    (43, 2, 1536, 'text index 43 doc 2 row 4'),
    (30, 2, 2048, 'text index 30 doc 2 row 2'),
    (42, 2, 3072, 'text index 42 doc 2 row 3'),
    (12, 2, 5120, 'text index 12 doc 2 row 5'),
    

  • Example 2: update kalksad1 set brred=(4096+3072)/2 where kalk_id=43, which would change it to:

    (30, 2, 2048, 'text index 30 doc 2 row 2'),
    (42, 2, 3072, 'text index 42 doc 2 row 3'),
    (26, 2, 3584, 'text index 26 doc 2 row 1'),
    (43, 2, 4096, 'text index 43 doc 2 row 4'),
    (12, 2, 5120, 'text index 12 doc 2 row 5'),
    

    Only when there's no gap between rows where the target should be, you'd need to first renumber rows using for example:

    update kalksad1 set brred=_brred*1024
    from (
      select row_number() over (order by brred) as _brred, kalk_id as _kalk_id
      from kalksad1
      where brkalk=2
      order by _brred desc
    ) as _
    where kalk_id=_kalk_id;
    

    This would be much aster than changing every row between source and target. But this'll only matter when there may be many rows to change.

提交回复
热议问题