Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2663 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2  3
Auteur Sujet :

[ASP][SQL] comment faire un SELECT DISTINCT en ayant plusieurs champs?

n°1906170
claudelana
Posté le 17-07-2009 à 14:43:22  profilanswer
 

Reprise du message précédent :
J'ai un problème de selection avec un distinct qui ne veut pas faire ce que je voudrais.
N'étant pas un virtuose de la BDD et après une recherche sur le net je suis arrivé sur ce poste qui ne date pas d'hier :) Donc, je me suis
permis de poster mon souci ici en espèrant que quelqu'un veuille bien m'aider.
 
J'ai une table produit dans une base de données access qui est composée des champs suivant :
Tout les champs ne sont pas représentés ici (trop nombreux)
 
Numéro, Code_Article, Désignation_Article, Code_Rayon, Désignation_Rayon, Code_Famille, Désignation_Famille, Code_S_Famille, Désignation_S_Famille, Code_Fournisseur, Nom_Fournisseur, Libelle_de_la_Taille, Code_Couleur, Désignation_Couleur, Code_Fabricant, Désignation_Fabricant, Prix_Vente_TTC
...., etc.
 
Je voudrais imprimer une étiquette générique par produit (sur cette étiquette doit figurer plusieurs champs)
 
Je prends par exemple parmit tous les produits de la table des chaussures qui ont les même données dans tous les champs sauf pour les champs taille et couleur ( ces deux champs ne figurent pas sur l'étiquette)
 
(extrait de la table produit)
 
Num CodeArt DésignArt  DésignRayon DésignFam DésignSFam NFour       Taille   DésignCoul DésignFabr     Prix
07   00153    Chauhiver  Chaussures  Chaussons Velcros        ANDREA     32       Noir          Andrea      115,00
08   00153    Chauhiver  Chaussures  Chaussons Velcros        ANDREA     32.5    Marron       Andrea      115,00
09   00153    Chauhiver  Chaussures  Chaussons Velcros        ANDREA     33       Vert          Andrea 115,00
10   00153    Chauhiver  Chaussures  Chaussons Velcros        ANDREA     33.5    Rouge        Andrea 115,00
11   00153    Chauhiver  Chaussures  Chaussons Velcros        ANDREA     34       Blanc         Andrea 115,00
37   00154    Chauhiver  Chaussures  Chaussons Enfants        ANDREA     26       Marron       Andrea  41,00
38   00154    Chauhiver  Chaussures  Chaussons Enfants       ANDREA     27       Vert          Andrea  41,00
48   00157    Chauhiver  Chaussures  Chaussons Lacets        ANDREA     32       Rouge         Andrea 108,00
49   00157    Chauhiver  Chaussures  Chaussons Lacets        ANDREA     32.5     Noir           Andrea 108,00
50   00157    Chauhiver  Chaussures  Chaussons Lacets        ANDREA     33        Noir           Andrea 108,00
78   00162    Chauhiver  Chaussures  Chaussons Velcros       BORÉAL      2 UK     Vert           Boréal  78,90
79   00162    Chauhiver  Chaussures  Chaussons Velcros       BORÉAL      2.5 UK  Vert           Boréal  78,90
80   00162    Chauhiver  Chaussures  Chaussons Velcros       BORÉAL      3 UK     Vert           Boréal  78,90
 
 
J'ai essayé ceci "SELECT DISTINCT Code_Article FROM produit"
 
Mais ca ne me sort que le code article alors que je voudrais avoir plusieurs champ d'inscris sur mon étiquette.
 
Si cela était possible j'aurais aimé quelque chose comme çà ( mais ce ne marche pas!) "SELECT (DISTINCT Code_Article), champ1, champ2, champ3, etc... FROM produits" ou ceci "SELECT (DISTINCT Code_Article), * FROM produits"  
 
 
j'ai essayé ceci également "SELECT DISTINCT Code_Article, champ1, champ2, champ3 FROM produit" mais ca me renvoi pas tout comme je le voudrais.
 
pour avoir comme résultat ( par exemple) une étiquette unique du genre :
 
Num CodeArt DésignArt   DésignRayon DésignFam DésignSFam NFour      Taille DésignCoul     DésignFabr       Prix
10    00153   Chaushiver Chaussures Chaussons Velcros        MARTIN     32       Bleu          MARTIN JO      115,00
38    00154   Chaushiver Chaussures Chaussons Enfants        ANDREA     33      Vert          Andrea             41,00
50    00157   Chaushiver Chaussures Chaussons Lacets         ANDREA    33       Noir           Andrea           108,00
78    00162   Chaushiver Chaussures Chaussons Velcros        BORÉAL     2 UK    Vert          Boréal              78,90
 
Le produit choisi dans le select distinct code_article m'importe peut car les champs sont presque tous identique et ceux qui sont différent ne me servent pas.
 
 
Si quelqu'un a une idée?
 
Merci d'avance

mood
Publicité
Posté le 17-07-2009 à 14:43:22  profilanswer
 

n°1906360
tet2neu
emmerdeur
Posté le 18-07-2009 à 19:29:13  profilanswer
 

Tu dis que les champs taille et couleur ne figurent pas sur l'étiquette mais dans ton exemple ils sont présents  [:payzan]
Et le champ "num" qui apparait également dans ton exemple semble être un numéro unique (identifiant ajouté par access ?) donc totalement inutile dans ton étiquette.

 

Peux-tu préciser si ta requête ne doit prendre en compte que les champs identiques, ou également d'autres champs ?

Message cité 1 fois
Message édité par tet2neu le 18-07-2009 à 19:29:26
n°1906362
claudelana
Posté le 18-07-2009 à 19:46:43  profilanswer
 

tet2neu a écrit :

Tu dis que les champs taille et couleur ne figurent pas sur l'étiquette mais dans ton exemple ils sont présents  [:payzan]  
Et le champ "num" qui apparait également dans ton exemple semble être un numéro unique (identifiant ajouté par access ?) donc totalement inutile dans ton étiquette.
 
Peux-tu préciser si ta requête ne doit prendre en compte que les champs identiques, ou également d'autres champs ?


 
Ce que je voulais dire c'est que les champs Tailles et Couleur ne seront pas inscrit sur l'étiquette.
 
En faite et visiblement si je fais un "SELECT DISTINCT CodeArt FROM Produit"
 
Quand j'imprime mes étiquettes, il me sort uniquement le champ CodeArt en evitant de me mettre les doublons, ce que je veux. Par contre je voudrais pouvoir également imprimer plusieurs autre champs sur mes étiquettes.
 
Si je fais "SELECT DISTINCT CodeArt, DésignRayon,  DésignFam FROM Produit" Il va supprimer les doublons dans ces trois champs, ce que je voudrais éviter. Donc mon idée (qui n'estpas bonne) était "SELECT [DISTINCT CodeArt] ( et uniquement sur ce champ) FROM Produit" et que je puisse imprimer tous les champs de la table sauf taille et couleur.
 
Je pene que dans access on ne peut pas travailler sur plusieurs champs si on ne met uniquement derriere le select qu'un seul champ. et ce que ej voudrais arrivé a faire c'est pouvoir afficher ou imprimer tous les champs que je veux en utilisant uniquement un select sur le CodeArt.
 
 
J'espere que j'ai été compréhensible ?
 
Claude

n°1906758
claudelana
Posté le 20-07-2009 à 12:17:09  profilanswer
 

J'ai trouvé une solution mais elle est un peu barbare. J'aimerais savoir s'il existe une requête pour éviter ce code ?  
 
<!--#Include File="odbc_open.asp"-->
<%
Dim objRS
Set objRS = Server.CreateObject("ADODB.Recordset" )
Set objRS00 = Server.CreateObject("ADODB.Recordset" )
 
'/ ** Requête SELECT DISTINCT sur 3 champs **/
strSQL = "SELECT DISTINCT Article, Rayon, Famille FROM MaTable WHERE Rayon='01' ORDER BY Article, Rayon, Famille"
 
'/ ** ouverture du recordset **/
objRS.Open strSQL, Conn, 3, 3
 
'/ ** Si ou moin un enregistrement est trouvé **/
If NOT(objRS.EOF AND objRS.BOF) Then  
 
'/ ** On boucle jusqu'à la fin **/
   DO WHILE NOT objRS.EOF
 
'/** On recherche un seul enregistrement dans la table (TOP 1) pour pouvoir récupèrer tous les champs **/
 
    strSQL00 = "SELECT TOP 1 * FROM MaTable WHERE Article='"&objRS("Article" ) &"' ORDER BY Rayon, Famille"
 
    objRS00.Open strSQL00, Conn, 3, 3
'/ ** Si l'enregistrement est trouvé on le récupère **/
    If NOT(objRS00.EOF AND objRS00.BOF) Then  
    response.write "<br> : " & objRS00("Numéro" ) & " " & objRS00("Désignation" ) & " " & objRS00("Description" ) & " " & objRS00("Prix" ) & " " & etc. ...
    End If
    objRS00.CLOSE
    objRS.MOVENEXT
   LOOP
End If
SET objRS00 = NOTHING
objRS.CLOSE
SET objRS =NOTHING
%>
%><!--#Include File="odbc_close.asp"-->
 
Mon idée c'est de faire un DISTINCT sur un seul champ (voir 3 maxi dans mon cas) mais surtout avoir un acces sur tous les champs de la table.
 
Si quelqu'un a une idée ? Mon code serait certainement plus propre si je pouvait le remplacer par une requête.
 
Merci d'avance de votre réponse

n°1906853
tet2neu
emmerdeur
Posté le 20-07-2009 à 15:38:06  profilanswer
 

J'ai vraiment du mal à saisir où tu veux en venir.
Si tu fais un distinct sur 3 champs et que tu récupères tous les autres champs, tu te retrouves avec toutes les lignes, le distinct ne sert à rien.
Autant faire un SELECT * FROM MaTable WHERE Rayon='01' [:jkley]  
 

n°1906856
tet2neu
emmerdeur
Posté le 20-07-2009 à 15:42:54  profilanswer
 

OK je viens de saisir avec ton code au dessus.
En fait tu prends les 3 champs de ton distinct, et la première ligne trouvée pour les autres.

 

Donc en fait, dans ton cas tu peux oublier le distinct et faire un group by

 

Si a, b et c sont les 3 champs de ton distinct et d, e et f les autres champs :

 
Code :
  1. select
  2.   a,
  3.   b,
  4.   c,
  5.   min(d) d,
  6.   min(e) e,
  7.   min(f) f
  8. from MatTable
  9. where ....
  10. group by
  11.   a,
  12.   b,
  13.   c
  14. order by...
 


Ca te sort tes 3 champs + le min trouvé pour les autres.


Message édité par tet2neu le 20-07-2009 à 15:43:57
n°2108273
longshot41
Marié
Posté le 27-10-2011 à 01:02:59  profilanswer
 

Navré de déterrer un vieux sujet, mais apparement si je suis tombé dessus, c'est que d'autres aussi.
 
La solution serait en rajoutant la clause having après le groupe by
 
groupe by Email, Nom, Prénom HAVING count( DISTINCT email ) = 1
 
Voir dans la doc, en fonction du type de base de donnée, mais ca doit être assez standard
 

n°2108445
lasnoufle
La seule et unique!
Posté le 27-10-2011 à 19:45:53  profilanswer
 

Sujet de qualité, avec des déterrages de qualité aussi. Ca m'fait un peu chier de répondre d'ailleurs, mais vu l'énormité postée au-dessus...

longshot41 a écrit :

La solution serait en rajoutant la clause having après le groupe by
 
groupe by Email, Nom, Prénom HAVING count( DISTINCT email ) = 1


Trop pas. Ta clause HAVING ne sert absolument à rien, elle ne filtre rien. Preuve par l'exemple:

create table test(mail varchar2(10), prenom varchar2(10), nom varchar2(10))
 
create table succeeded.
insert into test(mail, prenom, nom) values ('mail1','prenom1','nom1')
 
1 rows inserted
insert into test(mail, prenom, nom) values ('mail1','prenom2','nom2')
 
1 rows inserted
select distinct mail, nom, prenom
from test
group by mail, nom, prenom
having count(distinct mail)=1
 
MAIL       NOM        PRENOM      
---------- ---------- ----------  
mail1      nom1       prenom1    
mail1      nom2       prenom2    
 
2 rows selected


J'ai pas trop lu le reste mais la "vraie" réponse au premier post ca aurait plutot été de nettoyer ses données voire de revoir son modèle: s'il s'attend à ce qu'une adresse soit affectée à une unique personne et que c'est pas le cas, perso je considère que c'est un problème de données.
 
Un truc qui "marche" si on veut quand meme avoir qu'une seule ligne, c'est comme indiqué deux posts au-dessus:

create table test(mail varchar2(10), prenom varchar2(10), nom varchar2(10))
 
create table succeeded.
insert into test(mail, prenom, nom) values ('mail1','prenom1','nom1')
 
1 rows inserted
insert into test(mail, prenom, nom) values ('mail1','prenom2','nom2')
 
1 rows inserted
select distinct mail, min(nom), min(prenom)
from test
group by mail
 
MAIL       MIN(NOM)   MIN(PRENOM)  
---------- ---------- -----------  
mail1      nom1       prenom1      
 
1 rows selected


A+


---------------
C'était vraiment très intéressant.
n°2108786
tet2neu
emmerdeur
Posté le 30-10-2011 à 16:49:55  profilanswer
 

marrant ce topic, 10 ans après on arrive encore à nous proposer des trucs qui marchent pas :D

n°2119656
elievar2
Posté le 05-01-2012 à 11:42:09  profilanswer
 

Hello,
 
Je me demande si c'est possible tout de même avec "distinct".
Comme vous dites, il faudrait pouvoir preciser quelle des lignes on souhaite conserver (parmis les doublons du champ mail).
 
On va vouloir affichier MAIL, NOM, PRENOM et DATE, et ne choisir que la première occurence d'un MAIL unique.
Si l'on souhaite n'importe lequel, on n'eftectuera pas de tri supplémentaire. Mais en général, on cherche le 1er mail ou le dernier mail envoyé, ce qui implique un tri par date.
 
C'est exactement ce que je recherche, et je suis sur que cela est possible, mais je n'arrive pas à le faire (et ce malgré les 2 pages de post que je viens de voir).
 
L'idée serait de faire un TOP 1 sur un champs precis de la selection choisi.
 
Je pense que ce n'est pas la fonction distinct, car dépends du résultat du tableau retourné par le select et donc semble s'executer en dernier.
 
Cela doit être une autre methode. Si je trouve, je passserais une tête ici :)
 
Dur dur :)
 
Merci tout de même.
 
 
 
 
 
 
 

mood
Publicité
Posté le 05-01-2012 à 11:42:09  profilanswer
 

n°2119787
lasnoufle
La seule et unique!
Posté le 05-01-2012 à 17:49:40  profilanswer
 

Pas sur d'avoir compris ce que tu veux vu que si c'est ce que j'ai compris, c'est assez simple. Par exemple si tu veux le mail le plus récent:

create table test(mail varchar2(10), prenom varchar2(10), nom varchar2(10), date_mail date);
create table succeeded.

 

insert into test(mail, prenom, nom, date_mail) values ('mail1','prenom1','nom1', sysdate);
1 rows inserted

 

insert into test(mail, prenom, nom, date_mail) values ('mail1','prenom2','nom2', sysdate-1);
1 rows inserted

 

insert into test(mail, prenom, nom, date_mail) values ('mail2','prenom3','nom3', sysdate-4);
1 rows inserted

 

insert into test(mail, prenom, nom, date_mail) values ('mail2','prenom4','nom4', sysdate-3);
1 rows inserted

 

select *
from test;
MAIL       PRENOM     NOM        DATE_MAIL                
---------- ---------- ---------- -------------------------
mail1      prenom1    nom1       05-JAN-12                
mail1      prenom2    nom2       04-JAN-12                
mail2      prenom3    nom3       01-JAN-12                
mail2      prenom4    nom4       02-JAN-12                

 

4 rows selected

 

select t.mail, t.nom, t.prenom, t.date_mail
from (select mail, max(date_mail) as maxdate
      from test
      group by mail) temp
join test t on t.mail = temp.mail and t.date_mail = temp.maxdate;
MAIL       NOM        PRENOM     DATE_MAIL                
---------- ---------- ---------- -------------------------
mail1      nom1       prenom1    05-JAN-12                
mail2      nom4       prenom4    02-JAN-12                

 

2 rows selected

 

drop table test;
 drop table test succeeded.


Bon ca reste "facile" tant que tu te tiens au plus récent/plus ancien grace aux fonctions min & max. Si tu veux le 3ème plus récent ca va compliquer un peu.

 

D'ailleurs en écrivant ca, j'me suis apercu que ma réponse précédente stait aussi de la merde, décidément ce thread est maudit. Déjà ya pas besoin de distinct de tte facon, et en plus si les données c'est:
insert into test(mail, prenom, nom) values ('mail1','prenom1','nom2')
insert into test(mail, prenom, nom) values ('mail1','prenom2','nom1')
Mon truc renvoyait visiblement du caca.

 

Edit: ah mais OK je viens de relire, tu veux utiliser un distinct à tout prix. Ptin c'est pas mon jour. Mais je pense pas que ca soit possible alors.


Message édité par lasnoufle le 05-01-2012 à 17:51:40

---------------
C'était vraiment très intéressant.
n°2121104
tet2neu
emmerdeur
Posté le 12-01-2012 à 23:00:34  profilanswer
 

elievar2 a écrit :

Hello,

 

Je me demande si c'est possible tout de même avec "distinct".
Comme vous dites, il faudrait pouvoir preciser quelle des lignes on souhaite conserver (parmis les doublons du champ mail).

 

On va vouloir affichier MAIL, NOM, PRENOM et DATE, et ne choisir que la première occurence d'un MAIL unique.
Si l'on souhaite n'importe lequel, on n'eftectuera pas de tri supplémentaire. Mais en général, on cherche le 1er mail ou le dernier mail envoyé, ce qui implique un tri par date.

 

C'est exactement ce que je recherche, et je suis sur que cela est possible, mais je n'arrive pas à le faire (et ce malgré les 2 pages de post que je viens de voir).

 

L'idée serait de faire un TOP 1 sur un champs precis de la selection choisi.

 

Je pense que ce n'est pas la fonction distinct, car dépends du résultat du tableau retourné par le select et donc semble s'executer en dernier.

 

Cela doit être une autre methode. Si je trouve, je passserais une tête ici :)

 

Dur dur :)

 

Merci tout de même.

 



tu dédoublonnes pas en une seule requête simple, et surtout pas avec un distinct.

 
Code :
  1. select a.NOM, a.PRENOM, a.MAIL, a.DATE
  2. from ma_table a
  3. inner join (select MAIL, max(DATE) DATE_MAX
  4.            from ma_table
  5.            group by MAIL) b
  6. on a.MAIL = b.MAIL and a.DATE = b.DATE_MAX


Message édité par tet2neu le 12-01-2012 à 23:02:44
n°2263343
sql_dba06
Posté le 27-07-2015 à 14:43:01  profilanswer
 

Hello, vous pouvez utiliser row_number() qui donne un numéro de ligne suivant des paramètres, entre autre ici on dédoublonne sur mail, prénom & nom.
Deuxième étapes, ajouter un select sur le premier select et filtrer sur rnk=1 (1er couple seulement):
 
SELECT *
FROM
(
SELECT DISTINCT mail,prenom,nom,
 row_number() OVER (PARTITION BY mail, nom, prenom ORDER by nom) as rnk
FROM liste  
WHERE mail LIKE '%@%'
)
WHERE rnk=1

n°2263378
tet2neu
emmerdeur
Posté le 27-07-2015 à 18:04:22  profilanswer
 

je crois que c'était important de relancer une nouvelle fois ce topic de la préhistoire :o

n°2286419
viriis
Posté le 12-08-2016 à 11:59:58  profilanswer
 

Lol le pire c'est que personne a trouvé de solution :)

n°2286461
tet2neu
emmerdeur
Posté le 12-08-2016 à 17:11:29  profilanswer
 

normal, il n'y a pas de solution
 
En tout cas tu m'as fait peur, j'ai cru à un nouveau post du genre "si si chez moi ça marche avec un distinct/group by" :D

n°2286462
viriis
Posté le 12-08-2016 à 17:12:21  profilanswer
 

lol :)

n°2287376
Skanzo
Posté le 05-09-2016 à 12:06:46  profilanswer
 

Bonjour  :hello:  
 
Énorme problème de logique pour tout ceux qui veulent absolument utiliser DISTINCT...
 
Dans mon cas ROW_NUMBER() fonctionne très bien.
 

Code :
  1. SELECT * FROM (SELECT P_Id,I_Id,ROW_NUMBER() OVER (PARTITION BY I_Id ORDER BY P_Id DESC) AS RowNum...
  2. ... WHERE RowNum = 1

n°2287401
antac
..
Posté le 05-09-2016 à 22:42:03  profilanswer
 

Allez je propose ça (sans tester) et pour MySQL :

Code :
  1. SELECT DISTINCT (SELECT nom FROM matable t1 WHERE t1.mail=matable.mail ORDER BY nom LIMIT 1 ), mail
  2. FROM
  3. matable


 
Quand au SGBD qui autorise un GROUP BY sans mettre tous les champs du Select, c'est le cas de MySQL  :)


Message édité par antac le 05-09-2016 à 22:47:30
n°2287635
tet2neu
emmerdeur
Posté le 09-09-2016 à 14:47:21  profilanswer
 

ouais, bah tu aurais peut-être dû tester avant de poster.
Je vois pas comment une telle requête pourrait fonctionner.

 

Ta sous-requête doit être dans le "from", pas dans le "select".

 

Ensuite, cette sous-requête retourne tous les noms correspondant à un mail.
Donc si on a 2 noms différents pour un mail, même avec un distinct derrière, on se retrouve avec le même problème qu'à l'origine de ce topic. Tu sais, ce problème qui a été mal posé 15 ans presque jour pour jour avant ton post.

 

En gros, ça ferait exactement la même chose que le simple select distinct nom, mail from matable

 

Bref, je ne comprends toujours pas pourquoi certains continuent à tenter de répondre alors qu'il n'y a pas de solution.

 

Laissez ce topic sombrer tranquillement dans les abîmes de l'internet mondial svp !

 

edit : et concernant le fait que mysql autorise l'ajout de champs dans le select qui ne sont pas dans le group by, c'est vrai, mais ça prend une valeur au hasard
Alors à moins que le choix de la valeur (la première trouvée ? le min ? le max ?) n'ait aucune importance, on ne peut quand même pas laisser penser que c'est une syntaxe correct.

Message cité 1 fois
Message édité par tet2neu le 09-09-2016 à 14:50:49
n°2287642
antac
..
Posté le 09-09-2016 à 15:04:38  profilanswer
 

tet2neu a écrit :

ouais, bah tu aurais peut-être dû tester avant de poster.
Je vois pas comment une telle requête pourrait fonctionner.
 
Ta sous-requête doit être dans le "from", pas dans le "select".
 
Ensuite, cette sous-requête retourne tous les noms correspondant à un mail.
Donc si on a 2 noms différents pour un mail, même avec un distinct derrière, on se retrouve avec le même problème qu'à l'origine de ce topic. Tu sais, ce problème qui a été mal posé 15 ans presque jour pour jour avant ton post.
 
En gros, ça ferait exactement la même chose que le simple select distinct nom, mail from matable
 
Bref, je ne comprends toujours pas pourquoi certains continuent à tenter de répondre alors qu'il n'y a pas de solution.
 
Laissez ce topic sombrer tranquillement dans les abîmes de l'internet mondial svp !
 
edit : et concernant le fait que mysql autorise l'ajout de champs dans le select qui ne sont pas dans le group by, c'est vrai, mais ça prend une valeur au hasard
Alors à moins que le choix de la valeur (la première trouvée ? le min ? le max ?) n'ait aucune importance, on ne peut quand même pas laisser penser que c'est une syntaxe correct.


 
Et pourtant, je viens de tester et ça marche bien :-)
Cette sous-requête renvoi LE PREMIER nom par ordre alphabétique correspondant à un mail (d'où le LIMIT 1) et c'est pour ça que je peux faire une sous requête dans le SELECT car il n'y a toujours qu'un seul résultat (en fait ça agit comme une fonction).  
D'où le fait que ça te renvoi pour chaque adresse e-mail distincte le premier nom qui correspond  :jap:

n°2287644
antac
..
Posté le 09-09-2016 à 15:10:31  profilanswer
 

Exemple pour une table ayant deux colonnes nom et mail contenant :
("Roger","roger@mail.com" ),
("Médor","medor1@mail.com" ),
("Bernard","bernard@mail.com" ),
("Joséphine","antoine@mail.com" ),
("Antoine","antoine@mail.com" )
 
Le résultat de la requête :

Code :
  1. SELECT DISTINCT (SELECT nom FROM matable t1 WHERE t1.mail=matable.mail ORDER BY nom LIMIT 1 ) AS nom, mail
  2.     FROM
  3.     matable


est :  
Antoine / antoine@mail.com
Bernard / bernard@mail.com
Roger / roger@mail.com
Médor / medor1@mail.com


Message édité par antac le 09-09-2016 à 15:13:54
n°2287645
kao98
...
Posté le 09-09-2016 à 15:14:45  profilanswer
 

antac a écrit :


 
Et pourtant, je viens de tester et ça marche bien :-)
Cette sous-requête renvoi LE PREMIER nom par ordre alphabétique correspondant à un mail (d'où le LIMIT 1) et c'est pour ça que je peux faire une sous requête dans le SELECT car il n'y a toujours qu'un seul résultat (en fait ça agit comme une fonction).  
D'où le fait que ça te renvoi pour chaque adresse e-mail distincte le premier nom qui correspond  :jap:


+1
tet2neu je vois pas pkoi on ne pourrait pas mettre une sous requête dans un select, à partir du moment où l'on ne renvois qu'un résultat. C'est même assez courant.
 
Donc après 15 ans, on a bien une réponse qui semble valide sur ce topic  [:jar jar]  
 
Pour la peine, une version SQL Server (suffit de remplacer LIMIT 1 par un TOP 1) :
 

Code :
  1. CREATE TABLE #matable (
  2. mail varchar(50),
  3. nom varchar(10)
  4. )
  5.  
  6. INSERT INTO #matable values ('email@1.com', 'nom 1')
  7. INSERT INTO #matable values ('email@1.com', 'nom 2')
  8. INSERT INTO #matable values ('email@2.com', 'nom 3')
  9.  
  10. SELECT DISTINCT (SELECT TOP 1 nom FROM #matable t1 WHERE t1.mail=#matable.mail ORDER BY nom), mail
  11. FROM
  12. #matable
  13.  
  14. DROP TABLE #matable


 


nom 1 email@1.com
nom 3 email@2.com


 

Spoiler :

Par contre, je dis pas que c'est pertinent comme requête :o


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
n°2287646
tet2neu
emmerdeur
Posté le 09-09-2016 à 15:19:22  profilanswer
 

antac a écrit :


 
Et pourtant, je viens de tester et ça marche bien :-)
Cette sous-requête renvoi LE PREMIER nom par ordre alphabétique correspondant à un mail (d'où le LIMIT 1) et c'est pour ça que je peux faire une sous requête dans le SELECT car il n'y a toujours qu'un seul résultat (en fait ça agit comme une fonction).  
D'où le fait que ça te renvoi pour chaque adresse e-mail distincte le premier nom qui correspond  :jap:


j'avais pas vu le LIMIT, en effet
 
Mais pour le coup, on en revient au même point qu'il y a des années, c'est à dire qu'il faut arriver à choisir le nom que l'on veut garder quand un mail correspond à plusieurs noms.
Et moi, personnellement, je préfère une règle clairement définie pour faire ce choix, et ne pas laisser le SGBD me retourner celui qu'il va rencontrer en premier.
 
Évidemment qu'il y a des solutions techniques pour répondre à la question.
Mais ça n'a pas de sens sauf si, encore une fois, on se fout complètement des données renvoyées, on veut juste des données.

n°2287648
kao98
...
Posté le 09-09-2016 à 15:23:05  profilanswer
 

tet2neu a écrit :


j'avais pas vu le LIMIT, en effet
 
Mais pour le coup, on en revient au même point qu'il y a des années, c'est à dire qu'il faut arriver à choisir le nom que l'on veut garder quand un mail correspond à plusieurs noms.
Et moi, personnellement, je préfère une règle clairement définie pour faire ce choix, et ne pas laisser le SGBD me retourner celui qu'il va rencontrer en premier.
 
Évidemment qu'il y a des solutions techniques pour répondre à la question.
Mais ça n'a pas de sens sauf si, encore une fois, on se fout complètement des données renvoyées, on veut juste des données.


On a fait le choix, dans les exemples précédents, de prendre le 1er nom trouvé par ordre alphabétique (ORDER BY nom). Ce n'est arbitraire du coup, et c'est sûrement pas le SGBD qui choisit.
 
Selon la table, juste en modifiant l'ORDER BY, tout est possible. Avec un champ type "created_at", on peut prendre le premier qui a été enregistré, ou le dernier ... bref, il suffit d'établir une règle métier, elle n'est pas difficile à implémentée.


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
n°2287650
antac
..
Posté le 09-09-2016 à 15:28:13  profilanswer
 

Tout dépend la règle que tu fixes... Imaginons que c'est pour faire du mailing et que tu ne veux envoyer qu'un mail par adresse avec dans le texte le nom, du genre "Bonjour Arnaud...", cela ne me semble pas déconnant.
 
La seule solution pour avoir tous les noms sur une seule colonne côté SQL (séparé par une virgule par exemple), c'est de passer par une vraie fonction qui va utiliser un curseur construisant une chaîne avec la liste des noms correspondants à l'adresse mail passé en paramètre...
 
Mais bon... quitte à faire un truc comme ça, il vaut mieux renvoyer tout et modéliser comme tu veux côté front...

Message cité 1 fois
Message édité par antac le 09-09-2016 à 15:33:41
n°2287651
tet2neu
emmerdeur
Posté le 09-09-2016 à 15:37:08  profilanswer
 

Oui donc on en revient toujours à la même chose. On décide de la façon de sélectionner, et ensuite on peut faire une requête qui marche.
 
Quand je disais qu'il n'y a aucune solution, je partais du principe que si on ne nous explique pas ce qu'on attend comme résultat, on ne peut pas trouver une solution.
A l'époque, en 2001, l'auteur de la question n'avait pas été clair sur la façon sélectionner le nom qu'il veut récupérer, ou en tout cas il a été mal compris.
S'il avait répondu sur les critères de ce choix, il aurait eu sa réponse.
 
Quand le sujet a été relancé des années plus tard, c'était avec une succession de trucs qui, dans le meilleur des cas, ne filtraient rien du tout, et le reste du temps ne fonctionnaient pas. D'où un certain agacement à chaque fois que le sujet remontait :D

n°2287652
tet2neu
emmerdeur
Posté le 09-09-2016 à 15:39:42  profilanswer
 

antac a écrit :

Tout dépend la règle que tu fixes... Imaginons que c'est pour faire du mailing et que tu ne veux envoyer qu'un mail par adresse avec dans le texte le nom, du genre "Bonjour Arnaud...", cela ne me semble pas déconnant.
 
La seule solution pour avoir tous les noms sur une seule colonne côté SQL (séparé par une virgule par exemple), c'est de passer par une vraie fonction qui va utiliser un curseur construisant une chaîne avec la liste des noms correspondants à l'adresse mail passé en paramètre...
 
Mais bon... quitte à faire un truc comme ça, il vaut mieux renvoyer tout et modéliser comme tu veux côté front...


oui enfin on est bien d'accord qu'à la base, quand on a une liste d'e-mail avec des noms différents, c'est qu'on a des données à nettoyer. Et le problème se règlera de lui même

n°2287654
antac
..
Posté le 09-09-2016 à 15:42:42  profilanswer
 

Pas forcément, plusieurs personnes peuvent partager la même adresse e-mail (adresse de service, mari et femme...).  
 
Dans ce cas là, tu supprimes le mari ou la femme ?
 
Ensuite la solution existe mais elle nécessite l'utilisation d'une fonction et d'un curseur (ce qui n'est pas implanté dans tous les SGBD...)


Message édité par antac le 09-09-2016 à 15:49:17
n°2287656
tet2neu
emmerdeur
Posté le 09-09-2016 à 15:58:46  profilanswer
 

la plupart du temps si tu essaies de t'inscrire sur un site avec un mail déjà existant, tu te fais jeter.  
Et si on tombe sur un cas où ça marche, c'est qu'on est pas sur un site très "pro".
Au pire tu envoies 2 mails, un pour le mari et un pour la femme. Ils se sont inscrit  2 fois, ils auront 2 mails :D

n°2287658
antac
..
Posté le 09-09-2016 à 16:15:20  profilanswer
 

Je donne une solution complète donc avec mon exemple et pour MySQL (mais transposable à beaucoup de SGBD)
 

Code :
  1. DELIMITER $$
  2. CREATE DEFINER=`root`@`%` FUNCTION `list_mail`(p_Mail VARCHAR(250)) RETURNS VARCHAR(1000) CHARSET utf8
  3. BEGIN
  4.   DECLARE _nom VARCHAR(250);
  5.   DECLARE retour VARCHAR(1000) DEFAULT '';
  6.   DECLARE _EOF INT DEFAULT 0;
  7.   DECLARE _EOF_ParcoursNom INT DEFAULT 0;
  8.   DECLARE _curLstNom CURSOR FOR
  9.    SELECT nom FROM matable WHERE mail=p_Mail;
  10.    DECLARE CONTINUE HANDLER FOR NOT FOUND SET _EOF = 1;
  11.  
  12.   OPEN _curLstNom;
  13.  lectureNom:
  14.  LOOP
  15.   FETCH  _curLstNom INTO _nom;
  16.   SET _EOF_ParcoursNom = _EOF;
  17.   IF _EOF_ParcoursNom THEN
  18.    CLOSE _curLstNom;
  19.    LEAVE lectureNom;
  20.   END IF;
  21.   SET retour = CONCAT(retour,IF(retour<>'',', ',''),_nom);
  22.  END LOOP lectureNom;
  23.   RETURN retour;
  24.     END$$
  25. DELIMITER ;


 
et la requête :

Code :
  1. SELECT DISTINCT list_mail(mail) AS noms, mail
  2.     FROM
  3.     matable


 
ce qui donnera un résultat sous la forme :
"Arnaud, Joséphine" | "arnaud@mail.com"
"Bernard" | "bernard@mail.com"
"Roger" | "roger@mail.com"

Message cité 1 fois
Message édité par antac le 09-09-2016 à 16:15:45
n°2287660
antac
..
Posté le 09-09-2016 à 16:26:02  profilanswer
 

tet2neu a écrit :

la plupart du temps si tu essaies de t'inscrire sur un site avec un mail déjà existant, tu te fais jeter.  
Et si on tombe sur un cas où ça marche, c'est qu'on est pas sur un site très "pro".
Au pire tu envoies 2 mails, un pour le mari et un pour la femme. Ils se sont inscrit  2 fois, ils auront 2 mails :D


 
Je ne juge pas pas sur le fait que le site est ou n'est pas professionnel, etc... La problématique peut s'appliquer à d'autres cas que celui-ci.
La solution est soit, arbitrairement prendre une seule valeur désignée selon une règle métier (dernier arrivé, ordre alphabétique, etc...) et on fait une sous requête dans le SELECT (le plus simple).
Soit on veut tout avec un séparateur et dans ce cas on doit passer soit par une fonction stockée soit le faire après avoir tout renvoyé côté back office.
 
Je pense maintenant qu'on peut clôturer ce sujet (vieux de 15 ans  :jap:)

n°2287661
kao98
...
Posté le 09-09-2016 à 16:30:33  profilanswer
 

antac a écrit :

Je donne une solution complète donc avec mon exemple et pour MySQL (mais transposable à beaucoup de SGBD)
 

Code :
  1. DELIMITER $$
  2. CREATE DEFINER=`root`@`%` FUNCTION `list_mail`(p_Mail VARCHAR(250)) RETURNS VARCHAR(1000) CHARSET utf8
  3. BEGIN
  4.   DECLARE _nom VARCHAR(250);
  5.   DECLARE retour VARCHAR(1000) DEFAULT '';
  6.   DECLARE _EOF INT DEFAULT 0;
  7.   DECLARE _EOF_ParcoursNom INT DEFAULT 0;
  8.   DECLARE _curLstNom CURSOR FOR
  9.    SELECT nom FROM matable WHERE mail=p_Mail;
  10.    DECLARE CONTINUE HANDLER FOR NOT FOUND SET _EOF = 1;
  11.  
  12.   OPEN _curLstNom;
  13.  lectureNom:
  14.  LOOP
  15.   FETCH  _curLstNom INTO _nom;
  16.   SET _EOF_ParcoursNom = _EOF;
  17.   IF _EOF_ParcoursNom THEN
  18.    CLOSE _curLstNom;
  19.    LEAVE lectureNom;
  20.   END IF;
  21.   SET retour = CONCAT(retour,IF(retour<>'',', ',''),_nom);
  22.  END LOOP lectureNom;
  23.   RETURN retour;
  24.     END$$
  25. DELIMITER ;


 
et la requête :

Code :
  1. SELECT DISTINCT list_mail(mail) AS noms, mail
  2.     FROM
  3.     matable


 
ce qui donnera un résultat sous la forme :
"Arnaud, Joséphine" | "arnaud@mail.com"
"Bernard" | "bernard@mail.com"
"Roger" | "roger@mail.com"


 
C'est un peu beaucoup pour faire un group_concat :o
 
MySql toujours :
 

Code :
  1. SELECT mail, GROUP_CONCAT( `nom` )
  2. FROM matable
  3. GROUP BY mail


 
Bon, ça c'est juste pour MySql par contre :/


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
n°2287662
antac
..
Posté le 09-09-2016 à 16:35:45  profilanswer
 

Ben oui, je donne une solution "transposable" à d'autres SGBD qui ne disposent pas forcément du GROUP_CONCAT :) (et pis j'ai mis un espace après la virgule :D)

Message cité 1 fois
Message édité par antac le 09-09-2016 à 16:35:58
n°2287663
kao98
...
Posté le 09-09-2016 à 16:48:08  profilanswer
 

antac a écrit :

Ben oui, je donne une solution "transposable" à d'autres SGBD qui ne disposent pas forcément du GROUP_CONCAT :) (et pis j'ai mis un espace après la virgule :D)


Code :
  1. SELECT mail, GROUP_CONCAT( `nom`  SEPARATOR ', ')
  2.    FROM matable
  3.    GROUP BY mail


:o
 
Pis les autres SGBD ils ont PIVOT :o²
 
 

Spoiler :


;)


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
n°2287664
antac
..
Posté le 09-09-2016 à 16:50:01  profilanswer
 

Quoi qu'il en soit, en 2 heures on a plus de réponses correctes qu'en 15 ans :) (Vive l'évolution)

n°2287666
kao98
...
Posté le 09-09-2016 à 16:57:22  profilanswer
 

Après moi je valide toujours pas la viabilité de la demande :o [:yiipaa:1]


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
n°2287670
MaybeEijOr​Not
but someone at least
Posté le 09-09-2016 à 17:55:34  profilanswer
 

tet2neu a écrit :

En fait, il veut un seul enregistrement par mail alors qu'un mail peut être associé à plusieurs couples nom/prénom. Ce qui est tout à fait impossible à moins de n'en choisir qu'un de façon arbitraire (un min(NOM) ???)


 
La réponse a bien été donnée il y a 8 ans.
 
Après vous pouvez toujours vous amuser à reformuler le problème mais ça devient difficile de suivre.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2287671
kao98
...
Posté le 09-09-2016 à 17:58:35  profilanswer
 

MaybeEijOrNot a écrit :


 
La réponse a bien été donnée il y a 8 ans.
 
Après vous pouvez toujours vous amuser à reformuler le problème mais ça devient difficile de suivre.


tet2neu il y a 8 ans disait que  

Citation :

Ce qui est tout à fait impossible à moins de n'en choisir qu'un de façon arbitraire


Non, ce n'est pas impossible, c'est tout à fait possible. Et il ne suffit pas d'en choisir de façon arbitraire, il suffit d'en choisir un selon une règle précise, qui n'a certes pas été précisée ici, mais c'est du domaine du possible.


---------------
Kao ..98 - Uplay (R6S) : kao98.7.62x39 - Origin (BF4, BF1) : kntkao98
n°2287672
MaybeEijOr​Not
but someone at least
Posté le 09-09-2016 à 18:04:48  profilanswer
 

Avec "min(NOM)" il supposait déjà que c'était possible avec une règle préétablie je pense.
Je dis juste que la réponse avait été apportée, vous pouvez toujours reposer le problème comme vous le voulez et le résoudre mais ça rend le topic compliqué à suivre car vous pouvez reformuler le problème autant de fois que vous le voulez.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2287673
sebdej
Posté le 09-09-2016 à 18:08:07  profilanswer
 

Je vous propose :
 

Code :
  1. SELECT mail, A.nom FROM
  2. test A
  3. WHERE NOT EXISTS (SELECT 1 FROM test B WHERE A.mail = B.mail AND A.nom > B.nom)


 
Ici on prend le premier email en triant par nom (A.nom > B.nom), on peut toujours mettre un autre critère à condition que ce soit une relation d'ordre.

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3

Aller à :
Ajouter une réponse
 

Sujets relatifs
Asp detection de champ vide dans un recordset[ASP]Date
[Asp / VB ] Connexion distante a une base de donnée[ASP] Pilote ODBC Microsoft Access erreur ...
[ASP]Fonction replaceqcm, à plusieurs réponses !?
ASP - Arrondir.. ou tronquage partie entière...[MYSQL] Comment faire si deux champs portent le même nom?
[ASP][SQL] une requête pour connaitre la structure d'une table ??? 
Plus de sujets relatifs à : [ASP][SQL] comment faire un SELECT DISTINCT en ayant plusieurs champs?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR