2009-07-25 15 views
8

Obecnie próbuję skonstruować nieco trudną instrukcję Select MySQL. Oto, co usiłuję osiągnąć:Deklaracja Select MySQL DISTINCT dla wielu kolumn

Mam tabeli tak:

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, co chciałbym zrobić, to być w stanie wybrać/grupie przez stringID (obraz, że stringID jest gwintowane) i nie ma tego duplikatu. Ponadto chciałbym wybrać najbardziej aktualny wiersz stringID (który w powyższym przykładzie to uniqueID 3).

Dlatego gdybym zapytanie do bazy danych, to powrót następujących (z najnowszym uniqueID na górze):

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. 

Mam nadzieję, że to ma sens. Dziękuję ci za pomoc.

+2

Państwo 100% pewności uniqueID zawsze będzie najwyższa ID w tabeli? Jeśli nie, proponuję dodać sygnaturę czasową dla najnowszego. – lexu

+0

Rzeczywiście mam kolumnę znacznika czasu (nie uwzględniony w powyższym przykładzie). Więc w jaki sposób chciałbym wtedy użyć kolumny z datownikiem? Czy MAX działa z kolumną znacznika czasu? Dzięki. –

Odpowiedz

9

Spróbuj wykonać następujące czynności. To może nie być najbardziej efektywny zapytania, ale to będzie działać:

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

To zapytanie pomogło najbardziej. Ponadto zastąpiłem "uniqueID" powyższą sugestią lexu, używając znacznika czasu. Bardzo dziękuję za pomoc. –

+2

Znalazłem to szukając rozwiązania podobnego problemu. To dobre rozwiązanie, ale można zwiększyć wydajność, używając tabeli tymczasowej zamiast podselekcji. Utwórz tabelę tymczasową w oparciu o wybór podrzędny, a następnie wybierz miejsce podrzędne w głównym zapytaniu, wybierz opcję * z tabeli tymczasowej na swoim miejscu. W moim zestawie danych 80000 wierszy, metoda podselekcji trwała minuty, podczas gdy użycie tabeli tymczasowej zajęło około 15 sekund. – GordonM

2

Edit: W oparciu o nowe informacje dostarczone przez OP w komentarzu, to byłoby lepiej, aby opierając się na 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 

Jeżeli, jak lexu wspomina w komentarzu, jesteś pewien, że najwyższą wartość uniqueID zawsze odpowiada najnowszym tematem, można to zrobić:

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 

Co zasadniczo oznacza: wróć do mnie tylko te zapisy z data_table, gdzie nie ma wyższej wartości uniqueID.

+1

To będzie działać gorzej. Podzapytanie nie używa żadnej z kolumn superqueries, dlatego jest obliczane tylko raz. 'Max' jest znacznie szybszy niż próba porównania każdego identyfikatora jeden po drugim. Co więcej, join będzie musiał wtedy zastosować klauzulę 'where'. Podzapytanie utworzy jednak tablicę asocjacyjną, która posłuży jako odnośnik do każdego identyfikatora. Ergo, tylko jedno porównanie i nie musimy sprawdzać kolumny po wykonaniu wszystkich porównań. – Eric

+0

@Eric - Twój argument ma sens, ale [niestety MySQL obecnie nie działa w ten sposób] (http: // stackoverflow.com/questions/3417074/why-would-an-in-condition-be-slower-than-in-sql/3417190 # 3417190) –

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

FROM tblMyTBL 

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

Miałem podobną sytuację i znalazłem inne zapytanie. Spróbuj tego:

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

Podając kod, który rozwiązuje problem, najlepiej podać przynajmniej krótkie wyjaśnienie o tym, jak to działa, aby ludzie czytający nie musieli analizować go po linii, aby zrozumieć różnice. – 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); 
     } 
Powiązane problemy