首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在SQL (postgres)中实现优先级

如何在SQL (postgres)中实现优先级
EN

Stack Overflow用户
提问于 2012-01-12 16:40:57
回答 2查看 4.8K关注 0票数 0

我正在编写一些软件,它需要将项目存储在数据库中,这些项目需要有“优先级”,所以我们最终

代码语言:javascript
运行
复制
    ID  |  Name        |  Priority
--------+--------------+----------
    1   | Pear         |  4
    2   | Apple        |  2
    3   | Orange       |  1
    4   | Banana       |  3

所以现在,最重要的水果是橘子,然后是苹果,然后是香蕉,然后是梨。

现在,我想把梨放在第一位,所以梨,橘子,苹果,香蕉。这张桌子看起来像:

代码语言:javascript
运行
复制
    ID  |  Name        |  Priority
--------+--------------+----------
    1   | Pear         |  1
    2   | Apple        |  3
    3   | Orange       |  2
    4   | Banana       |  4

用PHP和Postgres实现这一点的最佳方法是什么?考虑到表不会超过12-13项,我考虑了整个表的SELECTing,并在更新所有内容之前重写了优先顺序。

*重要*

优先级可以按任何顺序更改,因此优先级7可以设置为优先级3(从而将所有低于优先级3的内容降至一个等级),并且我们需要缩小这个差距-优先事项7的项目已移至优先事项3中,保留在优先级列表中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-28 16:19:56

好的,这是我的尝试,以保持优先级的独特性和连续性。由trigger+function实现。最困难的部分是避免触发器内部的更新可能导致的无限递归。这是解决了污垢/颜色标志,必须放在桌子内。它的价值并不重要,只是它的变化。

代码语言:javascript
运行
复制
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE fruits
        ( id INTEGER NOT NULL PRIMARY KEY
        , zname varchar NOT NULL
        , priority INTEGER NOT NULL
        , flipflag boolean NOT NULL default false
        , CONSTRAINT unique_priority UNIQUE (priority) DEFERRABLE INITIALLY DEFERRED
        );
INSERT INTO fruits(id,zname,priority) VALUES
 (1  , 'Pear' ,4)
,(2  , 'Apple' ,2)
,(3  , 'Orange' ,1)
,(4  , 'Banana' ,3)
        ;

CREATE function shift_priority()
RETURNS TRIGGER AS $body$

BEGIN

        UPDATE fruits fr
        SET priority = priority +1
        , flipflag = NOT flipflag       -- alternating bit protocol ;-)
        WHERE NEW.priority < OLD.priority
        AND OLD.flipflag = NEW.flipflag -- redundant condition
        AND fr.priority >= NEW.priority
        AND fr.priority < OLD.priority
        AND fr.id <> NEW.id             -- exlude the initiating row
                ;
        UPDATE fruits fr
        SET priority = priority -1
        , flipflag = NOT flipflag
        WHERE NEW.priority > OLD.priority
        AND OLD.flipflag = NEW.flipflag
        AND fr.priority <= NEW.priority
        AND fr.priority > OLD.priority
        AND fr.id <> NEW.id
        ;
        RETURN NEW;
END;

$body$
language plpgsql;

CREATE TRIGGER shift_priority
        AFTER UPDATE OF priority ON fruits
        FOR EACH ROW
        WHEN (OLD.flipflag = NEW.flipflag AND OLD.priority <> NEW.priority)
        EXECUTE PROCEDURE shift_priority()
        ;

UPDATE fruits
SET priority = 1
WHERE id=1;

结果:

代码语言:javascript
运行
复制
SELECT * FROM fruits ORDER BY id;
NOTICE:  drop cascades to 2 other objects
DETAIL:  drop cascades to table tmp.fruits
drop cascades to function tmp.shift_priority()
DROP SCHEMA
CREATE SCHEMA
SET
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "fruits_pkey" for table "fruits"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "unique_priority" for table "fruits"
CREATE TABLE
INSERT 0 4
CREATE FUNCTION
CREATE TRIGGER
UPDATE 1
 id | zname  | priority | flipflag 
----+--------+----------+----------
  1 | Pear   |        1 | f
  2 | Apple  |        3 | t
  3 | Orange |        2 | t
  4 | Banana |        4 | t
(4 rows)
票数 3
EN

Stack Overflow用户

发布于 2012-01-12 17:05:56

单个事务中的两个更新在这样一个小表上应该可以很好地工作。

代码语言:javascript
运行
复制
create temp table priorities (
  id integer primary key,
  name varchar(15) not null,
  priority integer not null check (priority > 0 and priority < 100)
);

insert into priorities values 
(1,'Pear',4),
(2,'Apple',2),
(3,'Orange',1),
(4,'Banana',3);

-- Make Pear priority 1.
begin;
update priorities 
set priority = priority + 1
-- The value below is the priority you're aiming for. You want
-- Pear to be #1, so you use ">= 1".
where priority >= 1;

update priorities
set priority = 1 where name = 'Pear';
commit;

为了方便起见,您可以将其包装在存储过程中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8838729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档