2017-02-14 1 views
0

J'ai une table dans la base de données MySQL à laquelle les enregistrements sont ajoutés en continu. Je veux classer l'occurrence d'une valeur et l'enregistrer dans un nouveau champ.Mysql - classement basé sur l'occurrence d'une valeur

Je souhaite remplir le champ FruitRank, en fonction de l'occurrence du fruit, pour cette personne/ce nom en particulier.

Voici la table attendue - Nom et Fruit ajoutés à la table en temps réel. Le champ FruitRank devrait être calculé et mis à jour en temps réel. Que faire à ce propos?

Nom | Fruit | FruitRank (nouveau champ)

Amy | pomme | 1

Amy | pomme | 1

Amy | pomme | 1

Amy | orange | 2

Amy | orange | 2

Tom | raisins | 1

Tom | raisins | 1

Amy | kiwi | 3

Amy | kiwi | 3

Répondre

0

Vous pouvez écrire un déclencheur AFTER INSERT sur la table actuelle qui calcule le rang de fruits et insère les enregistrements dans une autre table. Vous pouvez utiliser la requête suivante pour calculer le rang:

SELECT COUNT(*) into rank 
FROM table 
WHERE person NEW.person and fruit = NEW.fruit; 

Une fois que vous obtenez le rang, vous pouvez exécuter la requête INSERT pour insérer les enregistrements dans une autre table. Le déclencheur est un exemple de AFTER INSERT.

0

A partir de vos données d'échantillon (la seule façon disponible pour définir la structure en quelque sorte ce que la table que vous avez à l'esprit) on ne sait pas pourquoi devriez-vous conserver différents dossiers avec absolument même charge utile.

Il semble que la seule chose que vous mettez à jour est le rang.

Donc dans ce cas, le rang viennent naturellement avec les mises à jour comme (plutôt que des inserts):

UPDATE fruitRanks SET FruitRank=FruitRank+1 WHERE Fruit = 'apple' AND Name='Amy'; 

Si vous avez la différence dans vos charges utiles - puis utilisez la table séparée (en liaison avec MISE À JOUR APRÈS trigger), il n'est pas nécessaire de conserver le rang dans chaque rangée alors.

Ou simplement laisser tomber le champ et le calculer quand vous en avez besoin avec la fonction d'agrégation de groupage &.

0

Voici deux approches possibles, au niveau de la base de données, selon vos besoins:

  • S'il y a une raison pour stocker un enregistrement dans la base de données pour chaque occurrence d'une personne/Fruit (par exemple, vous devez enregistrer le temps que le fruit a été mangé, etc), alors il n'y a aucune raison de stocker la valeur du rang dans la base de données, car cela nécessiterait un UPDATE avec chaque INSERT. Vous pouvez obtenir le rang avec une requête simple en utilisant COUNT(*).

  • S'il n'y a aucune raison de stocker chaque occurrence, vous ne devriez avoir qu'une entrée par combinaison personne/fruit avec une valeur de rang qui est mise à jour à chaque occurrence suivante.

Rang Récupéré avec fonction d'agrégation

requête pour obtenir le grade: (En supposant chaque occurrence est stocké dans Person_Fruit table)

SELECT person, fruit, COUNT(*) 
FROM person_fruit 
WHERE person = 'the_person' 
    AND fruit = 'the_fruit' 
GROUP BY 1, 2; 

Rang Stored dans la base de données

En supposant table Fruits (id, personne, fruit, rang), avec un multi-column index sur la personne et le fruit, de sorte que vous avez seulement une occurrence de chaque combinaison unique.

Avant INSERT/UPDATE, vérifier si la personne/Fruit existe déjà:

SELECT id 
FROM fruits 
WHERE name = 'the_name' AND fruit = 'the_fruit'; 

Si elle n'a pas, INSERT personne/Fruit d'une valeur de rang de 1, comme cela est le premier occurrence:

INSERT INTO fruits (id, person, fruit, rank) 
VALUES (NULL, 'the_person', 'the_fruit', 1); /* NULL should be replaced by auto-generated value, if set up for that */ 

Si elle le fait, UPDATE le classement:

UPDATE fruits 
SET rank = rank +1 
WHERE id = id  /* You can use id returned from previous `SELECT`, or Person AND Fruit */