@AlirezaSoori: Pomimo nazwy, idto tylko kolumna w tabeli. Nie ma gwarancji, że wartości w idkolumnie muszą być unikalne.
unutbu
1
@unutbu Zakładając, że idnie jest to klucz podstawowy ani unikalny :) Biorąc pod uwagę nazwę, istnieje duża szansa, że tak jest. Warto również zauważyć, że w zależności od używanego DBMS, podejście z podselektem może być znacznie mniej wydajne.
Michael Mior,
3
@MichaelMior: idmoże być kluczem obcym, w takim przypadku może nie być unikatowy. Przeprowadziłem kilka testów porównawczych set profiling = 1; ...; show profilesi wygląda na to, że nasze rozwiązania mają taką samą wydajność przy użyciu MySQL. Z mojej własnej wiedzy, czy wiesz, który DBMS ma gorszą wydajność dla podselekcji?
unutbu
1
Może to być klucz obcy, ale jak powiedziałem, po prostu zgaduję na podstawie nazwy, że tak nie jest. MySQL jest historycznie znany ze słabej wydajności w przypadku podselekcji. To znacznie się poprawiło w nowszych wersjach, więc zależy od używanej wersji. Jednak po ponownym przemyśleniu to konkretne zapytanie może być OK. Chociaż kilkakrotne wykonanie zapytania z profilowaniem niekoniecznie mówi wiele o względnej wydajności.
Michael Mior,
149
Ty też możesz to zrobić
SELECTrowFROMtableORDERBY id DESC LIMIT 1;
Spowoduje to posortowanie wierszy według ich identyfikatorów w porządku malejącym i zwrócenie pierwszego wiersza. To to samo, co zwrócenie wiersza z maksymalnym identyfikatorem. To oczywiście zakłada, że idjest wyjątkowy wśród wszystkich rzędów. W przeciwnym razie może istnieć wiele wierszy z maksymalną wartością dla, ida otrzymasz tylko jeden.
Aby konkretnie zrobić to, o co prosi OP, zrobiłbym to. Ale inne odpowiedzi zapewniają lepszą edukację na temat struktury SQL :)
MatBailie
@Dems Jak to? Nie podano żadnych wyjaśnień na temat innej odpowiedzi? Oczywiście ja też jestem temu winny :(
Michael Mior
Tylko te inne pytania poprawiają składnię bez refaktoryzacji logiki. Tak więc OP uczy się, jak poprawnie określić ten konkretny plik sql.
MatBailie
Słuszna uwaga :) Chociaż inne odpowiedzi prawdopodobnie nadal poprawiają logikę.
Michael Mior,
A co z wydajnością? Dostałem się tutaj z tego rodzaju zapytaniem, które już dla mnie działa, ale zastanawiałem się, czy to właściwy sposób. Czy ORDER BY nie jest operacją O (n * log n)?
dhill
27
SELECT*FROMtableWHERE id =(SELECT MAX(id)FROMTABLE)
@ shA.t SELECT entry FROM table WHERE id = MAX(id)nie zadziała ?!
oldboy
@ shA.t Ponadto próbuję zrobić coś takiego: SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified WHERE account_email = :account_email)przy czym potrzebuję tylko entry_timenajnowszego wpisu w bazie danych. Czy to stwierdzenie jest wystarczające, czy powinno być:SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified) AND account_email = :account_email
oldboy
Najnowszy wpis w wyniku zapytania nie ma zaufanego znaczenia, musisz mieć pole czasu wstawienia i tak dalej. Swoją drogą proszę o pytanie zadaj osobno, mam nadzieję, że zdobędziesz więcej uprzejmości -HTH;).
shA.t
17
Nie możesz dać, order byponieważ order byrobi "pełne skanowanie" na stole.
Następujące zapytanie jest lepsze:
SELECT*FROMtableWHERE id =(SELECT MAX(id)FROMtable);
ORDER BYnie wykona pełnego skanowania, jeśli założysz, że idjest to klucz podstawowy tabeli. (A jeśli tak nie jest, jest raczej słabo nazwane). Jeśli nie, jak spodziewasz MAX(id)się pracy bez pełnego skanowania tabeli? Jeśli nie ma indeksu, każda wartość musi zostać sprawdzona, aby znaleźć maksimum.
Michael Mior
@CakeLikeBoss No cóż, wypróbowałem zapytanie „order by” i twoje „SELECT * FROM table WHERE id = (SELECT MAX (id) FROM table);” zapytanie w tabeli 114 wierszy, podczas gdy to zapytanie trwało dokładnie 0,0004 sekundy za każdym razem, podczas gdy drugie zapytanie trwało od 0,0007 do 0,0010 sekund Powtórzyłem to kilka razy
prabhjot
1
Zawsze można też skorzystać z funkcji analitycznych, które zapewnią większą kontrolę
select tmp.row from ( select row, rank() over(partition by id order by id desc ) as rnk from table) tmp where tmp.rnk=1
Jeśli napotkasz problem z funkcją rank () w zależności od typu danych, możesz również wybrać row_number () lub dense_rank ().
Słowo kluczowe TOP nie działa w MySQL. To zapytanie nie zadziała.
Anirudha Gupta
@toddmo: MySQL! Sql-Server również nie jest pomocny dla innych osób. Masz na myśli MS-SQL?
raiserle
@raiserle, czy możesz mi pomóc znaleźć miejsce, w którym skomentowałem lub opublikowałem cokolwiek na to pytanie? Nigdzie nie widzę swojego nazwiska dołączonego do tego pytania.
Odpowiedzi:
Możesz użyć podselekcji:
Zwróć uwagę, że jeśli wartość
max(id)
nie jest unikalna, zwracanych jest wiele wierszy.Jeśli chcesz tylko jeden taki wiersz, użyj odpowiedzi @ MichaelMior,
źródło
id
to tylko kolumna w tabeli. Nie ma gwarancji, że wartości wid
kolumnie muszą być unikalne.id
nie jest to klucz podstawowy ani unikalny :) Biorąc pod uwagę nazwę, istnieje duża szansa, że tak jest. Warto również zauważyć, że w zależności od używanego DBMS, podejście z podselektem może być znacznie mniej wydajne.id
może być kluczem obcym, w takim przypadku może nie być unikatowy. Przeprowadziłem kilka testów porównawczychset profiling = 1; ...; show profiles
i wygląda na to, że nasze rozwiązania mają taką samą wydajność przy użyciu MySQL. Z mojej własnej wiedzy, czy wiesz, który DBMS ma gorszą wydajność dla podselekcji?Ty też możesz to zrobić
Spowoduje to posortowanie wierszy według ich identyfikatorów w porządku malejącym i zwrócenie pierwszego wiersza. To to samo, co zwrócenie wiersza z maksymalnym identyfikatorem. To oczywiście zakłada, że
id
jest wyjątkowy wśród wszystkich rzędów. W przeciwnym razie może istnieć wiele wierszy z maksymalną wartością dla,id
a otrzymasz tylko jeden.źródło
źródło
SELECT entry FROM table WHERE id = MAX(id)
nie zadziała ?!SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified WHERE account_email = :account_email)
przy czym potrzebuję tylkoentry_time
najnowszego wpisu w bazie danych. Czy to stwierdzenie jest wystarczające, czy powinno być:SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified) AND account_email = :account_email
Nie możesz dać,
order by
ponieważorder by
robi "pełne skanowanie" na stole.Następujące zapytanie jest lepsze:
źródło
ORDER BY
nie wykona pełnego skanowania, jeśli założysz, żeid
jest to klucz podstawowy tabeli. (A jeśli tak nie jest, jest raczej słabo nazwane). Jeśli nie, jak spodziewaszMAX(id)
się pracy bez pełnego skanowania tabeli? Jeśli nie ma indeksu, każda wartość musi zostać sprawdzona, aby znaleźć maksimum.Zawsze można też skorzystać z funkcji analitycznych, które zapewnią większą kontrolę
select tmp.row from ( select row, rank() over(partition by id order by id desc ) as rnk from table) tmp where tmp.rnk=1
Jeśli napotkasz problem z funkcją rank () w zależności od typu danych, możesz również wybrać row_number () lub dense_rank ().
źródło
Spróbuj z tym
źródło