查询:

$consulta = "UPDATE `list`
                SET `pos` = $pos
              WHERE `id_item` IN (SELECT id_item
                                    FROM lists
                                   WHERE pos = '$item'
                                ORDER BY pos DESC
                                   LIMIT 1)
                AND id_usuario = '$us'
                AND id_list = '$id_pl'";


事实是,此查询位于foreach内部,它想更新列表中项目的顺序。在我像这样之前:

$consulta = "UPDATE `list`
                SET `pos` = $pos
              WHERE `$pos` = '$item'
                AND id_usuario = '$us'
                AND id_list = '$id_pl'";


但是,当我更新pos 2-> 1,然后1-> 2时,结果是2的两倍且没有1 ...

这个查询有解决方案吗?

最佳答案

对列表中的项目重新编号非常棘手。当您使用多个单独的SQL语句对列表中的项目重新编号时,这将更加棘手。

您的内部sub-select语句也没有受到适当的约束。您需要额外的条件,例如:

AND id_list = '$id_pl'


可能有很多方法可以做到这一点,但是下面可能是最简单的一种方法。我假设:


未显示的foreach循环按所需顺序(1、2,...)生成$pos
$id_pl的值在循环中是恒定的
foreach循环为每次迭代提供$us$item的值
$id_pl$us$item的组合唯一标识list表中的行
最多可以担心100个pos
您可以在语句序列周围使用显式事务


建议的解决方案包括两个阶段:


为每行分配100 +位置,以将其放置在新位置
从每个位置减去100


此技术避免了有关是否已由同一查询重新读取已调整位置的行的任何复杂问题。

循环内:

foreach ...
    ...$pos, $item, $us...

    UPDATE list
       SET pos = $pos + 100
     WHERE id_item = '$item'
       AND id_usuario = '$us'
       AND id_list = '$id_pl'
       AND pos < 100
end foreach

UPDATE list
   SET pos = pos - 100
 WHERE id__list = '$id_pl';


如果您不知道列表的大小,则可以在循环中分配负pos值,然后在循环后转换为正pos,或者使用许多其他等效映射中的任何一个。关键是更新表,以使循环中的新pos号与旧数字脱节,然后在循环后调整新值。

替代技术创建一个临时表,该表将旧数字映射到新数字,然后执行单个UPDATE语句,从而在一次操作中将所有行的旧pos值更改为新的pos值。这可能会更有效,尤其是如果可以将映射表作为查询生成时,但这取决于重新编号是否是算法上的。所显示的技术虽然有些笨拙,但可以使其适用于任意重编号。

关于mysql - 使用SQL查询重新编号列表中的项目?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5366605/

10-11 22:11
查看更多