Mettre à jour de manière incrémentale

Recalculer des poids gauche-droite pour adapter à la représentation intervallaire

Le problème exposé dans ce sujet a été résolu.

Bonjour tout le monde (oui, il est tôt…) !

Je cherche à pouvoir regénérer les poids gauche-droite d'une table nouvellement convertie pour utiliser la représentation intervallaire. Je pensais au départ utiliser l'ID des éléments, mais comme il y a eu des suppressions, ça va générer des trous, ce qui n'est pas vraiment bien géré par l'outil. Je suis donc parti en quête de quelque chose qui me permettrait de pouvoir re-générer mes poids de manière propre, en tenant cependant un tant soit peu compte de l'ordre de création de mes éléments.

J'ai fini par concocter la requête suivante :

1
2
3
4
5
SET @rank=0;
UPDATE ma_table t
   SET t.lft = @rank * 2 + 1, t.rgt = (@rank + 1) * 2, @rank = @rank + 1
    WHERE tt.id <> 1
    ORDER BY `champ1` DESC, `champ2` DESC

Cependant, si je suis ici, c'est parce que cela ne semble pas fonctionner, du moins avec MySQL 5.7.9 : j'ai droit à une notification d'erreur de syntaxe pour la partie @rank = @rank + 1.

Est-ce que quelqu'un pourrait aimablement me montrer comment faire, s'il y a juste une petite astuce que j'ai loupé ?

Merci  :)

+0 -0

Ce n'est peut-être pas du tout ça mais est-ce que tu as essayé @rank := @rank + 1 ? Des fois ce n'est pas forcément clair quand utiliser = et :=.

Sinon si ça ne marche pas avec la variable, ça sera 36 fois plus lent mais il y a sans doute moyen de s'en sortir avec quelque chose du genre :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
create temporary table tmp (
id int unsigned not null,
left int not null,
right int not null,
primary key(id)
);

insert into tmp (id, left, right)
select id,
(select * from (select max(right)+1 from tmp) z1),
(select * from (select max(right)+2 from tmp) z2)
from tatable
where id!=1
order by xxx asc, yyy asc;

update tatable set 
left = (select left from tmp z where z.id=tatable.id),
right = (select right from tmp z where z.id=tatable.id)
where id!=1;

drop table tmp;
+1 -0

Ce n’est peut-être pas du tout ça mais est-ce que tu as essayé @rank := @rank + 1 ? Des fois ce n’est pas forcément clair quand utiliser = et :=.

QuentinC

Apparemment, c’est surtout le fait d’avoir une "variable" qui pose problème. Je vais voir pour utiliser la table temporaire.

Edit

Ah, mais si la table est vide, MAX(rgt) vaut NULL. Et si on entre une ligne de départ, les nombres ne se mettent pas à jour, donc je me retrouve avec les mêmes valeurs pour rgt et lft pour tous les enregistrements…

Edit 2

Au final, j’ai fait en quelques étapes de plus, et probablement qu’on peut simplifier

UPDATE `ma_table`
SET `parent_id` = 1,
    `root_id` = 1,
    `lvl` = 0,
    `lft` = (`id`) * 2 - 1,
    `rgt` = (`id`) * 2
WHERE `id` <> 1;

CREATE TEMPORARY TABLE `temp` (
    `id` INT UNSIGNED NOT NULL,
    `lft` INT not null,
    `rgt` INT NOT NULL
);

INSERT INTO `temp`(`id`, `lft`, `rgt`)
SELECT
    `id`,
    (SELECT count(*) * 2 + 1
        FROM `ma_table` a1
        WHERE a1.`champ1` >= `ma_table`.`champ1`
            AND a1.`lft` > `ma_table`.`lft`),
    (SELECT (count(*) + 1) * 2
        FROM `ma_table` a2
        WHERE a2.`champ1` >= `ma_table`.`champ1`
            AND a2.`lft` > `ma_table`.`lft`),
FROM `ma_table`
WHERE `ma_table`.id <> 1
ORDER BY `champ1` DESC,
    `champ2` DESC;

UPDATE `ma_table` t
INNER JOIN `temp` ON t.id = `temp`.id
SET
    t.`lft` = `temp`.`lft`,
    t.`rgt` = `temp`.`rgt`;
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte