根据order列更新周围的行

mkh04yzy  于 2021-06-24  发布在  Mysql
关注(0)|答案(1)|浏览(344)

我需要设置一个自定义的顺序为类别时,添加新的,并改变现有的。我相信在这两种情况下,代码和sql查询是相同的。
在我的 webshop_categories -我有一张table sorting_order INT -我用来确定类别应该输出给查看者的顺序的列。
下面是我的表的一个简化示例(so=排序顺序):

id  |   name   |  so
--------------------
1   |   Shoes  |  1
2   |   Hats   |  2
3   |   Bags   |  3
4   |   Coats  |  4
5   |   Rings  |  5

添加未指定类别时,我只需填写表格,并按如下方式提交:
(这将添加一个新类别,并将其放在末尾。在这种情况下 so 将设置为6)

$so = $dbh->query('SELECT (MAX(so)+1) FROM webshop_categories WHERE so != 0')->fetchColumn();
$ins = $dbh->prepare('INSERT INTO webshop_categories (name, so)')->execute([$_POST['name'], $so]);

但有时我需要改变分类的顺序。
我可能需要把外套移到鞋帽之间。
这需要对周围的类别进行更新。
在这种情况下;帽子,或任何上面的东西,无论我把这个类别,现在需要做一个 +1so 列,以便为该移动腾出空间。但增长显然需要停止在大衣。
反之亦然。如果我把帽子移到外套和戒指之间,我需要做一个 -1 衣服和袋子。再一次。
实现这一目标的好方法是什么?
改变是通过 form select 选项在哪里 move to top (指 1 )以及 Move to after ?cat_name? .
我相信它将是相同的代码时,添加一个新的类别与预设的排序顺序。具有相同选项的相同选择列表。
我是否需要查询和获取所有需要 so 更新为 +/- 1 ,并循环进行更改?
或者有办法 +/- 1 在同一时间对所有人都不进行循环?
制作所有行的副本(放入一个php数组),删除它们,创建一个更新了的新列表 so ,然后将它们插回,不应该只是为了进行这些更改。。。但这是我发现的一种方法。。。

332nm8kg

332nm8kg1#

有多种方法可以做到这一点,但具体的方法实际上取决于您的结构。
也就是说,无论你如何接近它,你只需要增加或减少那些低于或高于你正在改变的:
新的时候 so 值为:
小于当前值(从4到2),选择小于当前值直至新值(2,3)的所有值,并按1递增
大于当前值(从2到4),选择所有大于当前值直到新值(4,3)并将其递减1
我建议只选择需要更新的行,这样“if less than”等逻辑就在select查询中了。然后使用结果数组进行更新。
例子:

1 = shoes
2 = hats
3 = bags
4 = coats
5 = rings

警告:这个代码是非常古老的学校,只是为了快速说明目的,以显示逻辑。它没有测试,可能有错误,测试前使用。
示例代码函数将更改任何大于或小于的值,例如4到2,或2到4,等等

// You'd retrieve the requested change data from your form (or whatever)
update_categories_so(
    (int) $_POST['category_id'],
    (int) $_POST['current_so'],
    (int) $_POST['new_so']
);

/**
 * @param int $categoryIdForChangedSo
 * @param int $currentSo
 * @param int $newSo
 *
 * @return void
 */
function update_categories_so($categoryIdForChangedSo, $currentSo, $newSo)
{
    // Determine if incrementing or decrementing
    $increment = $newSo < $currentSo  ? true : false;

    // Set increment or decrement var for the update
    $changeBy = $increment ? '+' : '-';

    // Set the where clause to get the current category_ids
    // which would need to be updated
    $selectWhereClause = $increment
        ? "'so' >= $newSo AND 'so' < $currentSo"
        : "'so' <= $newSo AND 'so' > $currentSo";

    $selectSql = "
        SELECT
            `category_id`
        FROM
            `webshop_categories`
        WHERE
            {$selectWhereClause}
        ";

    // Return the results into $categoryIdsForUpdate

    // Update the categories which are affected by the main change,
    // from the array from the DB
    $updateOtherSoSql = "
        UPDATE
            `webshop_categories`
        SET
            'so' = 'so' {$changeBy} 1
        WHERE
            'category_id' IN ({$categoryIdsForUpdate})
        ";

    // Update the main one being changed
    $updateRequestedSosql = "
        UPDATE
            `webshop_categories`
        SET
            so = {$newSo}
        WHERE
            'category_id' = {$categoryIdForChangedSo}
        ";
}

我不知道如何处理错误,甚至不知道是否处理错误,但您可以返回结果-检查查询是否正常等
更多信息 $selectWhereClause ,了解where的工作原理:
不更新请求更新的(单独更新)
如果new“so”小于current,则在current之前从new(inc new)递增到1
如果new“so”大于current,则从current之后的1减为new(inc new)
更多信息 $categoryIdsForUpdate 从数据库返回的数据。下面的示例数组是将“so”4(coats)更改为2(当前为hats)时的数组(示例ID不是1-5,以避免与“so”值混淆) category_id => so ```
$categoryIdsForUpdate = [
10 => 1, // (shoes) not included as is less than new "so"
13 => 2, // (hats) incremented by 1
17 => 3, // (bags) incremented by 1
18 => 4, // (coats) not included as is current category_id
27 => 5, // (rings) not included as greater than current "so"
];

相关问题