4

有没有什么好的算法可以“填补”表格优先级(或任何其他)列的空白?例如

例子

我有一个结构如下的表:

id | text | subcategory | priority

它是这样填充的

1 | books    | NULL | 1
2 | dvds     | NULL | 2
5 | action   | 2    | 1
8 | romantic | 2    | 2
9 | fantasy  | 1    | 1
4 | sci-fi   | 1    | 2
6 | comics   | 1    | 3

在我的设计中,有一个更改子类别的选项,如果发生这种情况,优先级设置为“新”优先级,并且其值在当前所在的子类别中最高。
例如, 将“action (id:5)”子类别更改为“books ( id:1)”,它的优先级是 4,没关系,但是现在“浪漫 (id:8)”行的优先级为 2,并且它是 1,并且仅在子类别 dvds (id:2) 中。

1 | books    | NULL | 1
2 | dvds     | NULL | 2
8 | romantic | 2    | 2
9 | fantasy  | 1    | 1
4 | sci-fi   | 1    | 2
6 | comics   | 1    | 3
5 | action   | 1    | 4

-> 我将幻想 (id:9) 子类别更改为 dvds (id:2),我的优先级将是 3。

1 | books    | NULL | 1
2 | dvds     | NULL | 2
8 | romantic | 2    | 2
9 | fantasy  | 2    | 3
4 | sci-fi   | 1    | 2
6 | comics   | 1    | 3
5 | action   | 1    | 4

没关系,但是我需要一个可以自行重新排序所有内容的函数,因此我不必手动更改优先级列的值。所以优先级列从 1 开始。

间隙从 id 8、4 开始。此外,更改漫画类别,然后将其改回来,它会很乱,会有正确的顺序,但它看起来不像我预期的那么好(出于管理目的)。

有任何想法吗?伪代码逻辑会很好。

编辑-解决方案:伪代码+逻辑

由于我们知道类别中的行数,我们可以进行选择,将按优先级排序,因此我们可以为每个“新”优先级分配正确的数字。

例如:
有序选择返回优先级如下:1、4、5、9、10
count(select) = 5
所以“新”优先级必须如下:1、2、3、4、5。只需在 foreach 循环中分配 new价值的关键。

因为它在 codeigniter 中:
$this->category_model->getPriorities("2") 在我的案例 2 中按一个子类别的顺序 (ASC) 为您提供所有优先级。

public function prioritize(){
    $p = $this->category_model->getPriorities("2");
        for ($i = 1; $i < count($p)+1; $i++) { 
            echo "new[".$i."]->id[".$p[$i-1]->id."]->old_value[".$p[$i-1]->priority."]<br>";    
        }
}

输出:

new[1]->id[9]->old_value[1]
new[2]->id[13]->old_value[3]
new[3]->id[14]->old_value[5]
new[4]->id[15]->old_value[8]
new[5]->id[11]->old_value[10]
4

2 回答 2

2

UPDATE table as tb1, table as tb2 SET tb2.priority = tb2.priority - 1 WHERE tb2.priority > tb1.priority AND tb1.text = 'action' AND tb2.subcategory = tb1.subcategory;

这应该可以解决差距,每个具有更高 id 的项目都应该将其降低 1

即你在这个子类别中:

| priority |
|   1      |
|   2      |
|   3      |
|   4      |

如果您移动优先级 = 2 的项目

3 和 4 将作为 2 和 3 移动

PS:这只是差距的解决方案,因为移动问题已经在另一个答案中解决了。应该在移动之前完成,因为之后子类会发生变化,并且不会满足WHERE子句(来自旧子类的项目)


关于重新排序随机间隙:

假设我们有优先级:

5、10、11、12、18、20

我们想要制作为:

1、2、3、4、5、6

所以这里的最大数是20,需要标记为6

完成后,最大数量为 18,应该是 5。

所以每次你使用UPDATE ... SET ... WHERE priority = MAX(priority)它都会得到最大的优先级。

这是我的简单测试:

<?php
for ($i = 6; $i>=1; $i--) {
    echo "UPDATE table SET priority = $i WHERE priority = MAX(priority) AND subcategory = X;" . "<br/>";
}
?>

产生:

UPDATE table SET priority = 6 WHERE priority = MAX(priority) AND subcategory = X; // 20 becomes 6
UPDATE table SET priority = 5 WHERE priority = MAX(priority) AND subcategory = X; // 18 becomes 5
UPDATE table SET priority = 4 WHERE priority = MAX(priority) AND subcategory = X; // 12 becomes 4
UPDATE table SET priority = 3 WHERE priority = MAX(priority) AND subcategory = X; // 11 becomes 3
UPDATE table SET priority = 2 WHERE priority = MAX(priority) AND subcategory = X; // 10 becomes 2
UPDATE table SET priority = 1 WHERE priority = MAX(priority) AND subcategory = X; // 5 becomes 1

因此,您需要在选择子类别的位置进行 SELECT 操作,而不是“X”,然后您需要计算 while 循环的行数:

for ($i = $count_rows; $>=1; $i++) { ...

当然,您需要将语句放在正确的查询函数中,而不是回显它,但这是出于测试目的。

于 2013-05-21T11:44:01.717 回答
1
SELECT @NewPriority := MAX(priority)+1 FROM table WHERE category='$NewCategory';
UPDATE table SET category='$NewCategory', prioroty = @NewPriority WHERE id='$Id';
于 2013-05-21T11:31:22.183 回答