我的系统中有此页面,显示输入的所有类别。该表有三个字段如下:
主页显示所有条目(博客),并按类别分组。现在的想法是管理员可以更改“类别”的“优先级”,以便根据他认为合适的内容安排页面。
示例:
==============================
| 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");
}
有关如何构建的任何帮助?
答案 0 :(得分:2)
让我们处理一个更普遍的情况,而不是将Category5从优先级5移到优先级1.有两个(镜像)更好的例子:
在每种情况下,有两个未受影响的行(优先级为1和5的行),一行指定为移动,两行受“附带损害”影响。
UPDATE语句的大部分技巧都是使用SELECT语句,该语句从'before'状态为'after'状态生成正确的数据。另一个技巧是识别控制操作的参数。这里有两个参数:
我们可能需要单独的“向上移动”算法(将较低优先级类别移至较高优先级),以及“向下移动”(将较高优先级类别移至较低优先级)。
以下是所示的前后情景:
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 - 测试驱动的查询开发 - 我们可以分阶段生成列表:
不受高优先级影响的行:
SELECT cat_id, category, priority
FROM categories
WHERE priority < 2;
不受低优先级影响的行:
SELECT cat_id, category, priority
FROM categories
WHERE priority > (SELECT priority FROM categories WHERE category = 'Category4');
移动的行:
SELECT cat_id, category, 2 AS priority
FROM categories
WHERE category = 'Category4';
必须调整优先级的行:
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进行测试时,这产生了正确的答案。
“向下移动”的并行分析产生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浏览器或更紧密耦合)驱动。你上面的内容很复杂,但可以解释。而“可解释”意味着你也有可能“可维护”。