Mysql
 sql >> Base de données >  >> RDS >> Mysql

Système de marquage :questions de solution Toxi

Tout d'abord, "toxi" n'est pas un terme standard. Définissez toujours vos termes ! Ou au moins fournir des liens pertinents.

Et maintenant à la question elle-même...

Non, vous aurez 3 tables.

Vous êtes à peu près sur la bonne voie, à l'exception du fait que vous pouvez utiliser la nature basée sur les ensembles de SQL pour "fusionner" bon nombre de ces étapes. Par exemple, taguer un élément 1 avec des balises :'tag1', 'tag2' et 'tag3' peut être fait comme ceci...

INSERT IGNORE INTO tagmap (item_id, tag_id)
SELECT 1, tag_id FROM tags WHERE tag_text IN ('tag1', 'tag2', 'tag3');

Le IGNORE permet que cela réussisse même si l'élément est déjà connecté à certaines de ces balises.

Cela suppose que toutes les balises requises sont déjà dans tags . En supposant tag.tag_id est auto-incrémenté, vous pouvez faire quelque chose comme ceci pour vous assurer qu'ils sont :

INSERT IGNORE INTO tags (tag_text) VALUES ('tag1'), ('tag2'), ('tag3');

Il n'y a pas de magie. Si "l'élément est connecté à une étiquette particulière" est un élément de connaissance que vous souhaitez enregistrer, alors il aura pour avoir une sorte de représentation physique dans la base de données.

Vous voulez dire retaguer les éléments (et non modifier les balises elles-mêmes) ?

Pour supprimer toutes les balises qui ne figurent pas dans la liste, procédez comme suit :

DELETE FROM tagmap
WHERE
    item_id = 1
    AND tag_id NOT IN (
        SELECT tag_id FROM tags
        WHERE tag_text IN ('tag1', 'tag3')
    );

Cela déconnectera l'élément de toutes les balises sauf 'tag1' et 'tag3'. Exécutez INSERT ci-dessus et DELETE l'un après l'autre pour "couvrir" à la fois l'ajout et la suppression de balises.

Vous pouvez jouer avec tout cela dans le SQL Fiddle .

Corriger. Un point de terminaison enfant d'un FK ne déclenchera pas d'action référentielle (telle que ON DELETE CASCADE), seul le parent le fera.

BTW, vous utilisez ce schéma parce que vous voulez des champs supplémentaires dans les tags (à côté de tag_text ), à droite? Si vous le faites, ne pas perdre ces données supplémentaires simplement parce que toutes les connexions ont disparu est le comportement souhaité.

Mais si vous vouliez juste le tag_text , vous utiliseriez un schéma plus simple dans lequel la suppression de toutes les connexions reviendrait à supprimer la balise elle-même :

Cela ne simplifierait pas seulement le SQL, cela fournirait également un meilleur clustering .

À première vue, "toxi" peut sembler économiser de l'espace, mais ce n'est peut-être pas le cas dans la pratique, car il nécessite des tables et des index supplémentaires (et les balises ont tendance à être courtes).

Mesurez avant de décider de faire quelque chose comme ça. Mon SQL Fiddle mentionné ci-dessus utilise un ordre très délibéré des champs dans le tagmap PK, les données sont donc regroupées d'une manière très conviviale pour ce type de comptage (rappel :Les tables InnoDB sont groupées ). Vous devez avoir une quantité vraiment énorme d'éléments (ou exiger des performances exceptionnellement élevées) avant que cela ne devienne un problème.

Dans tous les cas, mesurez sur des quantités de données réalistes !