如何规范化/更新“订单”列

时间:2013-06-11 05:50:35

标签: sql postgresql

我有一个带有一些数据数据的表“mydata”:

id    name       position
===========================
4     foo        -3 
6     bar        -2 
1     baz        -1
3     knork      -1
5     lift       0
2     pitcher    0

我使用order by position ASC;

获取订购的表格

位置列值可能不唯一(由于某种原因未在此处描述:-),用于在SELECT期间提供自定义订单

我想做什么:

我想通过将唯一位置与不会破坏订单的每一行相关联来规范化表列“位置”。标准化后的最高位置应为-1。

希望得到的表格内容:

id    name       position
===========================
4     foo        -6 
6     bar        -5 
1     baz        -4
3     knork      -3
5     lift       -2
2     pitcher    -1

我尝试了几种方法但未能实现正确 update语句。

我猜这是使用

generate_series( -(select count(*) from mydata), -1) 

是获取position列的新值的一个很好的起点,但我不知道如何将生成的列数据合并到update语句中。

希望有人可以帮助我: - )

4 个答案:

答案 0 :(得分:6)

类似的东西:

with renumber as (
  select id,
         -1 * row_number() over (order by position desc, id) as rn
  from foo
)
update foo
  set position = r.rn
from renumber r
where foo.id = r.id
  and position <> r.rn;

SQLFiddle Demo

答案 1 :(得分:2)

试试这个 -

<强>查询:

CREATE TABLE temp
(
      id INT
    , name VARCHAR(10)
    , position INT
)

INSERT INTO temp (id, name, position)
VALUES 
    (4, 'foo', -3),
    (6, 'bar', -2),
    (1, 'baz', -1),
    (3, 'knork', -1),
    (5, 'lift', 0),
    (2, 'pitcher', 0)

SELECT 
      id
    , name
    , position = -ROW_NUMBER() OVER (ORDER BY position DESC, id) 
FROM temp
ORDER BY position

<强>更新

UPDATE temp
SET position = t.rn
FROM (
    SELECT id, rn = - ROW_NUMBER() OVER (ORDER BY position DESC, id) 
    FROM temp
) t
WHERE temp.id = t.id

<强>输出:

id          name       position
----------- ---------- --------------------
4           foo        -6
6           bar        -5
3           knork      -4
1           baz        -3
5           lift       -2
2           pitcher    -1

答案 2 :(得分:1)

@a_horse_with_no_name真的很接近真相 - 谢谢!

UPDATE temp 
  SET position=t.rn 
  FROM (SELECT 
            id, name, 
            -((select count( *) 
          FROM temp)
            +1-row_number() OVER (ORDER BY position ASC)) as rn
        FROM temp) t 
  WHERE temp.id=t.id;

SELECT * FROM temp ORDER BY position ASC;

请参阅http://sqlfiddle.com/#!1/d1770/6

答案 3 :(得分:0)

update mydata temp1, (select a.*,@var:=@var-1 sno from mydata a, (select @var:=0) b 
order by position desc, id asc) temp2
set temp1.position = temp2.sno
where temp1.id = temp2.id;