suprimer doublons sauf celui d'un min absolu

suprimer doublons sauf celui d'un min absolu - SQL/NoSQL - Programmation

Marsh Posté le 24-01-2014 à 02:19:13    

bonjour,
dans une table j'ai des 'doublons' que je veux supprimer sauf celui ayant la plus petite valeur.par exemple je prend le cas de 2 doublons:
id ,4, 2, 35
id ,11, 1, 4
 
je veux supprimer la ligne qui ne contient pas 1 qui est la plus petite valeur cad
garder seulement id ,11, 1, 4 car 1 est le min de 4,2, 35,11, 1, 4
 
ET si j'ai les 3 enregistrements
 
id ,4, 2, 35
id ,11, 1, 4
id ,0, 1, 9
 
je supprime tout sauf id ,0, 1, 9 car 0 est le min des valeurs (4, 2, 35 ,11, 1, 4 ,0, 1, 9)
 
Est ce possible avec une simple requête mysql
 
Merci

Reply

Marsh Posté le 24-01-2014 à 02:19:13   

Reply

Marsh Posté le 24-01-2014 à 16:38:48    

Salut
 
Je connais peu MySql mais une recherche rapide sur Google semble montrer qu'il n'y a pas de fonction pour decouper une chaine de caracteres; et si j'ai bien compris ce que tu demandes (car les champs a ta disposition, par exemple, ne sont pas tres clairs), ca va forcement bloquer a cause de ca.
 
Du coup "simple requete MySql" non. Il va falloir passer par un algo, donc par exemple declarer une procedure MySql, ou le faire en PHP, etc.
 
A+
G


---------------
C'était vraiment très intéressant.
Reply

Marsh Posté le 24-01-2014 à 22:56:24    


Bonjour  
Ce qui bloque est la requête ou les requêtes SQL qui me permettent d'effectuer cette tâche: je sais juste comment avoir le min des 3 champs mais seulement sur un enregistrement, genre

Code :
  1. least(c1,c2,c3)


Quant à comparer ce Min avec les Mins de tous les  autres enregistrements qui partagent le même ID; puis tirer l'enregistrement élu pour le garder en supprimant tous les autres, je n'arrive pas à formuler ça.
 
Par ailleurs MySQL supporte la fonction  

Code :
  1. substring(chaine,position,nb_caractères)


mais je ne pense pas qu'elle puisse être d'une grande utilité dans ma situation.
 
Enfin pour être plus précis sur le problème voici une autre manière de l'exposer:
les enregistrements n'ont de commun que le champ ID et cet ID n'est pas unique, la clé est un autoincrement.

Code :
  1. cle  ID C1  C2  C3
  2. ------------------
  3. 1234, id ,4, 2, 35
  4. 234, id ,11, 1, 4
  5. 6532, id ,0, 1, 9


 
Les champs c1, c2 et c3 sont des coûts.
 
La requête doit supprimer tous les enregistrements sauf
 

Code :
  1. 6532, id ,0, 1, 9


 
car  il contient 0 qui est le minimum absolu de tous les coûts ayant ID en commun.
 
Merci d'avance

Reply

Marsh Posté le 25-01-2014 à 03:20:51    

Tu veux dire que C1, C2 et C3 sont des champs separes? Si c'est le cas, du coup c'est possible. Un truc du genre:
 

DELETE FROM table WHERE cle NOT IN (
  SELECT t.cle
  FROM table t
  JOIN (
    SELECT id, MIN(min_local) as min_global
    FROM (
      SELECT id, LEAST(c1,c2,c3) as min_local
      FROM table
    )
  ) min_value ON min_value.id = t.id AND min_value.min_global = LEAST(t.c1,t.c2,t.c3)
)


Par contre si un ID a plusieurs lignes avec le cout minimum, ca les gardera toutes - a toi de voir si ca peut arriver, si c'est genant, et comment tu veux choisir quelle ligne garder.


---------------
C'était vraiment très intéressant.
Reply

Marsh Posté le 25-01-2014 à 13:29:12    

Merci beaucoup de cette réponse que je viens de tester mais qui m'a donné des erreurs qui sont certainement dues à mon incompréhension  ds la requête (je maîtrise pas encore les alias  :ouch: )
 
ma table s'appelle

Code :
  1. couts

et la clé s'appelle

Code :
  1. serie

, voici ce que j'ai écris
 

Code :
  1. DELETE FROM couts WHERE serie NOT IN (
  2.   SELECT t.serie
  3.   FROM table t
  4.   JOIN (
  5.     SELECT id, MIN(min_local) as min_global
  6.     FROM (
  7.       SELECT id, LEAST(c1,c2,c3) as min_local
  8.       FROM couts
  9.     )
  10.   ) min_value ON min_value.id = t.id AND min_value.min_global = LEAST(t.c1,t.c2,t.c3)
  11. )


 
Il me renvoie une erreur de syntaxe.
 
Est ce qu'il te semble que j'ai bien adapté ta requête au nom de ma table couts et à la clé serie?
 
Toutes mes excuses pour mon ignorance des ALIAS et merci d'avance
 

Reply

Marsh Posté le 25-01-2014 à 19:38:05    

Bonjour,
 
esaye :  

Code :
  1. DELETE FROM couts WHERE serie NOT IN (
  2.       SELECT t.serie
  3.       FROM couts t
  4.       JOIN (
  5.         SELECT id, MIN(min_local) as min_global
  6.         FROM (
  7.           SELECT id, LEAST(c1,c2,c3) as min_local
  8.           FROM couts
  9.         )
  10.       ) min_value ON min_value.id = t.id AND min_value.min_global = LEAST(t.c1,t.c2,t.c3)
  11.     )


Message édité par torwood3 le 25-01-2014 à 19:39:06

---------------
"La valeur d'un homme tient dans sa capacité à donner et non dans sa capacité à recevoir." Albert Einstein / "Dans la nature, tout a toujours une raison. Si tu comprends cette raison, tu n'as plus besoin de l'expérience." Léonard De Vinci
Reply

Marsh Posté le 25-01-2014 à 22:50:45    

Bonjour lasnoufle, merci torwood3,  
Merci de cette requête et de toute la peine que vous vous donnez pour moi. J'ai testé la requête précédente et voici l'erreur qu'il me sort :
 

Code :
  1. #1248 - Every derived table must have its own alias


 
Merci infiniment

Reply

Marsh Posté le 26-01-2014 à 17:53:20    

Re

 

Comme je disais, je connais pas trop mysql, mais d'apres google, ca a l'air d'etre une erreur "basique": visiblement, il faut toujours que les sous-requetes aient un alias en mysql.
Du coup, en partant de la reponse de torwood3, et en ajoutant un alias dans la sous-requete la plus a l'interieur:
   

DELETE FROM couts WHERE serie NOT IN (
          SELECT t.serie
          FROM couts t
          JOIN (
            SELECT id, MIN(min_local) as min_global
            FROM (
              SELECT id, LEAST(c1,c2,c3) as min_local
              FROM couts
            ) alias_quelconque
          ) min_value ON min_value.id = t.id AND min_value.min_global = LEAST(t.c1,t.c2,t.c3)
        )


Message édité par lasnoufle le 26-01-2014 à 17:53:55

---------------
C'était vraiment très intéressant.
Reply

Marsh Posté le 26-01-2014 à 23:36:07    

Bonjour lasnoufle, bonjour à tous,
 
Merci beaucoup de cette réponse qui -même si tu n'es pas un spécialiste de MySQL- me tirera certainement d'affaire, car elle fait effectivement disparaître l'erreur et surtout m'apprend quelque chose d'important pour l'avenir avec ce SGBD fabuleux qu'est MySQL.
 
Il subsite juste le message d'erreur qui suit:

Code :
  1. #1093 - You can't specify target table 'couts' for update in FROM clause


 
Ce qui m'intrigue c'est qu'il n'y a pourtant pas d'instruction update pour la table couts.
 
Merci d'avance.

Reply

Marsh Posté le 27-01-2014 à 15:50:57    

Interessant. Le DELETE est vu comme un UPDATE je suppose, et on dirait une "limitation" (a defaut d'un meilleur mot) de MySql: la requete retire des lignes de la table cout tout en utilisant cette meme table pour choisir les lignes a retirer, et on dirait que MySql ne "sait" pas gerer ca: si une ligne est retiree, doit-elle encore servir dans le calcul pour choisir celles restantes a retirer? Du coup, MySql empeche completement ce cas de figure d'arriver. Il y a peut-etre un parametre systeme pour changer ca...

 

Ca veut dire que en l'etat, tu ne vas pas pouvoir faire ca en une seule requete - au minimum, il va te falloir deux etapes: une pour calculer les lignes a garder (ou a enlever) et stocker la liste, et une pour faire le DELETE a partir de ta liste (et du coup, sans utiliser directement la table couts lors du delete).

 

Tu peux utiliser une table intermediaire pour ca, par exemple:

CREATE TABLE temp_couts_a_garder AS
SELECT t.serie
          FROM couts t
          JOIN (
            SELECT id, MIN(min_local) as min_global
            FROM (
              SELECT id, LEAST(c1,c2,c3) as min_local
              FROM couts
            ) alias_quelconque
          ) min_value ON min_value.id = t.id AND min_value.min_global = LEAST(t.c1,t.c2,t.c3);

(la syntaxe a peut-etre besoin d'etre ajustee)
puis

DELETE FROM couts WHERE serie NOT IN (SELECT serie FROM temp_couts_a_garder);

Puis evidemment, detruis ta table intermediaire.

DROP TABLE temp_couts_a_garder;


A+


Message édité par lasnoufle le 27-01-2014 à 15:52:40

---------------
C'était vraiment très intéressant.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed