2009-07-25 6 views
8

J'essaie actuellement de construire une déclaration MySQL Select un peu compliquée. Voici ce que je suis en train d'accomplir:MySQL Select Instruction DISTINCT pour plusieurs colonnes

J'ai une table comme ceci:

data_table 

uniqueID  stringID   subject 
    1    144   "My Subject" 
    2    144   "My Subject - New" 
    3    144   "My Subject - Newest" 
    4    211   "Some other column" 

Bascially, ce que je voudrais faire est d'être en mesure par la stringID (photo SELECT/GROUP que la stringID est threadé) et ne pas l'avoir dupliqué. De plus, j'aimerais CHOISIR la ligne stringID la plus récente, (qui dans l'exemple ci-dessus est uniqueID 3).

Par conséquent, si je devais interroger la base de données, il retourne les éléments suivants (avec le uniqueID le plus récent en haut):

uniqueID stringID subject 
4   211  "Some other column" 
3   144  "My Subject - Newest" //Notice this is the most recent and distinct stringID row, with the proper subject column. 

J'espère que cela a du sens. Merci pour votre aide.

+2

Êtes-vous certain à 100% uniqueID sera toujours le plus élevé ID dans le tableau? Sinon, je vous suggère d'ajouter un horodatage pour la dernière. – lexu

+0

J'ai effectivement une colonne timestamp (non inclus dans mon exemple ci-dessus). Alors, comment pourrais-je utiliser ma colonne timestamp alors? Est-ce que MAX fonctionne avec une colonne d'horodatage? Merci. –

Répondre

9

Essayez les solutions suivantes. Il pourrait ne pas être la requête la plus efficace, mais il fonctionnera:

SELECT uniqueID, stringID, subject 
FROM data_table 
WHERE uniqueID IN 
(
    SELECT MAX(uniqueID) 
    FROM data_table 
    GROUP BY stringID 
) 
ORDER BY uniqueID DESC 
+1

Cette requête a aidé le plus. De plus, j'ai remplacé le 'uniqueID' par la suggestion de lexu ci-dessus, en utilisant l'horodatage. Merci beaucoup pour votre aide. –

+2

J'ai trouvé cette recherche d'une solution à un problème similaire. C'est une bonne solution, mais l'utilisation d'une table temporaire à la place de la sous-sélection permet d'améliorer les performances. Créer une table temporaire basée sur le sous-sélection, puis où va le sous-sélection dans la requête principale, mettez select * à partir de la table temporaire à sa place. Sur mon ensemble de données de plus de 80000 lignes, la méthode de sous-sélection prenait quelques minutes, tandis que l'utilisation d'une table temporaire prenait à la place environ 15 secondes. – GordonM

2

Edit: Sur la base de nouvelles informations fournies par l'OP dans un commentaire, il serait préférable de compter sur uniqueID:

select t.uniqueID 
     , t.stringID 
     , t.subject 
     , t.your_timestamp_col 
from data_table t 
     left outer join data_table t2 
     on t.stringID = t2.stringID 
    and 
     t2.your_timestamp_col > t.your_timestamp_col 
where t2.uniqueID is null 

Si, comme Lexu mentionne dans un commentaire, vous êtes certain que la valeur la plus élevée uniqueID correspond toujours avec le dernier sujet, vous pouvez le faire:

select t.uniqueID 
     , t.stringID 
     , t.subject 
from data_table t 
     left outer join data_table t2 
     on t.stringID = t2.stringID 
    and 
     t2.uniqueID > t.uniqueID 
where t2.uniqueID is null 

Ce qui signifie fondamentalement: me renvoyer seulement les enregistrements de data_table où il n'existe pas de valeur plus élevée uniqueID.

+1

Il va effectivement faire pire. La sous-requête n'utilise aucune des colonnes de superqueries et, par conséquent, n'est calculée qu'une seule fois. Un 'max' est beaucoup plus rapide que d'essayer de comparer chaque identifiant un par un. De plus, la jointure devra alors appliquer la clause 'where'. La sous-requête, cependant, va créer une table de hachage qui sert de recherche à chacun des ID. Ergo, une seule comparaison, et nous n'avons pas à vérifier la colonne après toutes les comparaisons sont faites. – Eric

+0

@Eric - Votre argument est logique mais [malheureusement, MySQL ne fonctionne pas actuellement de cette façon] (http: // stackoverflow.com/questions/3417074/pourquoi-un-dans-une-condition-être-plus-lent-que-dans-sql/3417190 # 3417190) –

3
SELECT DISTINCT(a), 
    (SELECT DISTINCT(b)) AS b, 
    (SELECT DISTINCT(c)) AS c 

FROM tblMyTBL 

WHERE... 
Order By... 
Etc. 
0

J'ai eu une situation similaire et trouvé une requête différente. Essayez ceci:

SELECT MAX(uniqueID), stringID, subject 
FROM data_table 
GROUP BY stringID 
+0

Lorsque vous fournissez du code qui résout le problème, il est préférable de donner aussi au moins une courte explication de la façon dont cela fonctionne pour que les gens qui lisent ne doivent pas analyser mentalement ligne par ligne pour comprendre les différences. – Fluffeh

-1
private void LoadAllFamilyMembers(string relationShip) 
     { 
      lbFamilyMembers.SelectedIndexChanged -= new EventHandler(lbFamilyMembers_SelectedIndexChanged); 
      SqlCommand cmd = new SqlCommand("select familymemberid,name from FamilyMembers where relationship = @relationship", con); 
      cmd.Parameters.AddWithValue("@relationship", relationShip); 
      DataTable dt = new DataTable(); 
      SqlDataAdapter adapter = new SqlDataAdapter(cmd); 
      adapter.Fill(dt); 
      lbFamilyMembers.DataSource = dt; 
      lbFamilyMembers.DisplayMember = "name"; 
      lbFamilyMembers.ValueMember = "familymemberid"; 
      lbFamilyMembers.SelectedIndex = -1; 
      lbFamilyMembers.SelectedIndexChanged += new EventHandler(lbFamilyMembers_SelectedIndexChanged); 
     } 
Questions connexes