0

我的系统中有这个页面,显示所有输入的类别。该表包含三个字段,如下所示:

  1. cat_id
  2. 类别
  3. 优先

主页显示所有条目(博客)并按类别分组。现在的想法是管理员可以更改“类别”的“优先级”,以便根据他认为合适的内容排列页面。

例子:

==============================
| Category     |  Priority   |
==============================
|  Category1   |   1         |
|  Category2   |   2         |
|  Category3   |   3         |
|  Category4   |   4         |
|  Category5   |   5         |
===============================

这个想法是,当用户将类别 5 的优先级编辑为 1 时,每个类别的其余优先级小于编辑的优先级将通过将其增加 1 进行调整,这样就不会出现重复。

到目前为止,我只有这个。

if (isset($_POST['edit'])) {
         if (is_numeric($_POST['cat_id']))

include('connect.php');

    $id = $_POST['cat_id'];
    $category = $_POST['category'];
    $priority = $_POST['priority'];

    mysql_query("UPDATE category 
                 SET category='$category', priority='$priority'
                 WHERE cat_id='$id'") or die(mysql_error());


     header("Location: addctg.php");                     

    }

关于如何构建的任何帮助?

4

1 回答 1

2

让我们处理一个比将 Category5 从优先级 5 移动到优先级 1 更一般的情况。有两个(镜像)更好的例子:

  • 将类别 4 移至优先级 2。
  • 将类别 2 移至优先级 4。

在每种情况下,有两排不受影响(优先级为 1 和 5 的排),一排指定为移动,两排受影响为“附带损坏”。

UPDATE 语句的大部分技巧是制定一个 SELECT 语句,该语句从“之前”状态生成“之后”状态的正确数据。另一个技巧是识别控制操作的参数。这里有两个参数:

  1. 类别(名称) - 或等效的类别 ID 号。
  2. 类别的新优先级。

对于“上移”(将较低优先级的类别移至较高优先级)和“下移”(将较高优先级的类别移至较低优先级),我们可能需要单独的算法。

以下是说明之前和之后的场景:

Before                        Category4 to Priority 2       Category2 to Priority 4
========================      ========================      ========================
| Category  | Priority |      | Category  | Priority |      | Category  | Priority |
========================      ========================      ========================
| Category1 | 1        |      | Category1 | 1        |      | Category1 | 1        |
| Category2 | 2        |      | Category4 | 2        |      | Category3 | 2        |
| Category3 | 3        |      | Category2 | 3        |      | Category4 | 3        |
| Category4 | 4        |      | Category3 | 4        |      | Category2 | 4        |
| Category5 | 5        |      | Category5 | 5        |      | Category5 | 5        |
========================      ========================      ========================

让我们首先尝试“向上​​移动”算法。

提升

使用 TDQD——测试驱动的查询开发——我们可以分阶段生成列表:

  1. 高优先级不受影响的行:

    SELECT cat_id, category, priority
      FROM categories
     WHERE priority < 2;
    
  2. 低优先级不受影响的行:

    SELECT cat_id, category, priority
      FROM categories
     WHERE priority > (SELECT priority FROM categories WHERE category = 'Category4');
    
  3. 被移动的行:

    SELECT cat_id, category, 2 AS priority
      FROM categories
     WHERE category = 'Category4';
    
  4. 必须调整其优先级的行:

    SELECT cat_id, category, priority + 1 AS priority
      FROM categories
     WHERE priority >= 2
       AND priority < (SELECT priority FROM categories WHERE category = 'Category4');
    

显然,这 4 个查询可以通过 4 路 UNION 组合以生成完整的新排序。同样清楚的是,由于查询 1 和 2 选择了不变的行,我们只需要处理由查询 3 和 4 生成的发生变化的行。

因此,更改的行是:

SELECT cat_id, category, 2 AS priority
  FROM categories
 WHERE category = 'Category4'
UNION
SELECT cat_id, category, priority + 1 AS priority
  FROM categories
 WHERE priority >= 2
   AND priority < (SELECT priority FROM categories WHERE category = 'Category4');

现在我们只需要派生一个 UPDATE 语句来更改优先级(不更改类别 ID 或类别名称):

UPDATE categories
   SET priority = 
       (SELECT x.priority
          FROM (SELECT cat_id, 2 AS priority
                  FROM categories
                 WHERE category = 'Category4'
                UNION
                SELECT cat_id, priority + 1 AS priority
                  FROM categories
                 WHERE priority >= 2
                   AND priority < (SELECT priority FROM categories WHERE category = 'Category4')
               ) AS x
         WHERE x.cat_id = categories.cat_id
       )
 WHERE cat_id IN
       (SELECT cat_id
          FROM categories
         WHERE category = 'Category4'
        UNION
        SELECT cat_id
          FROM categories
         WHERE priority >= 2
           AND priority < (SELECT priority FROM categories WHERE category = 'Category4')
       );

主 UPDATE 语句中的 WHERE 子句可以简化,产生:

UPDATE categories
   SET priority = 
       (SELECT x.priority
          FROM (SELECT cat_id, 2 AS priority
                  FROM categories
                 WHERE category = 'Category4'
                UNION
                SELECT cat_id, priority + 1 AS priority
                  FROM categories
                 WHERE priority >= 2
                   AND priority < (SELECT priority FROM categories WHERE category = 'Category4')
               ) AS x
         WHERE x.cat_id = categories.cat_id
       )
 WHERE cat_id IN
       (SELECT cat_id
          FROM categories
         WHERE priority >= 2
           AND priority <= (SELECT priority FROM categories WHERE category = 'Category4')
       );

当针对在 Mac OS X 10.7.4 上运行的 IBM Informix Dynamic Server 11.70.FC2 进行测试时,这产生了正确答案。

下移

'Move Down' 的并行分析产生 UPDATE 语句:

UPDATE categories
   SET priority = 
       (SELECT x.priority
          FROM (SELECT cat_id, 4 AS priority
                  FROM categories
                 WHERE category = 'Category2'
                UNION
                SELECT cat_id, priority - 1 AS priority
                  FROM categories
                 WHERE priority <= 4
                   AND priority > (SELECT priority FROM categories WHERE category = 'Category2')
               ) AS x
         WHERE x.cat_id = categories.cat_id
       )
 WHERE cat_id IN
       (SELECT cat_id
          FROM categories
         WHERE priority <= 4
           AND priority >= (SELECT priority FROM categories WHERE category = 'Category2')
       );

代表作

最终的答案是以这样一种方式组合这些查询,无论命名的类别是向上还是向下移动,它都可以工作(如果该类别被提名留在同一个地方,它将什么都不做)。虽然我毫不怀疑可以开发这样的查询,但我认为不值得付出努力。您可以编写一个存储过程来获取类别名称和类别的新优先级,它会执行必要的 UPDATE 语句。这可以很容易地从 UI(Web 浏览器或更紧密耦合)驱动。你上面的内容很复杂,但是可以解释。而“可解释”意味着您也有机会“可维护”。

于 2012-09-14T03:41:06.867 回答