Kategorie: Programowanie

[SQL] Jak wybrać drugą największą wartość z kolumny?

Cześć! Cieszę się, że mnie odwiedziłeś/aś. Zanim przejdziesz do artykułu chciałbym zwrocić Ci uwagę na to, że ten artykuł był pisany kilka lat temu (2013-05-03) miej więc proszę na uwadzę że rozwiązania i przemyślenia które tu znajdziesz nie muszą być aktualne. Niemniej jednak zachęcam do przeczytania.

Zakładamy że mamy taką oto tabelę:

Osoby
——-
idOsoby
Imie
Wiek
Nazwisko

oraz takie dane:

IdOsoby Imie Wiek Nazwisko
1 Mateusz 21 Mazurek
2 Michał 36 Dorycki
3 Kamil 37 Dudło
4 Sebastian 19 Tabelowski
5 Łukasz 12 Wlazło
6 Maciej 36 Prędki

 

Chciałbym wybrać z tej tabeli wiek osoby która jest młodsza od najstaszej osoby ale starsza od pozostałych osób.

Czyli druga wartość jeśli byśmy sortowali malejąco po wieku.

Skorzystamy z podzapytań (subqueries). Zapytanie wewnętrzne zwracać będzie 2 pierwsze rekordy z tych posortowanych malejąco, czyli od największego do najmniejszego. A z tego wyniku wybierzemy najmniejszą wartość.

Czyli z podzapytania weźmiemy:

IdOsoby Imie Wiek Nazwisko
3 Kamil 37 Dudło
2 Michał 36 Dorycki

A następnie z tego weźmiemy najmniejszą wartość wieku. Co będzie równoznaczne z 2 co do kolejności malejącej wartość wieku z całej tabeli :)

Zapytanie:

1
2
3
SELECT MIN(Wiek) AS secondvalue
FROM
(SELECT TOP(2) * FROM dbo.Osoby ORDER BY Osoby.Wiek DESC) AS r
Dzięki za wizytę,
Mateusz Mazurek
Mateusz M.

Pokaż komentarze

  • Wydaje mi się, choć mogę się mylić, że TOP(2) nie jest tu właściwym rozwiązaniem.
    Sortując malejąco wiersze w tabeli (podzapytanie), otrzymujemy:

    -------------------------------
    Kamil Dudło 37
    Michał Dorycki 36 ← wybieramy tą osobę
    Maciej Predki 36 ← ale ta również jest dobrym kandydatem
    -------------------------------

    Moim zdaniem wynikiem zapytania powinny być obydwie w.w. osoby, ponieważ w zadaniu
    nie mamy żadnego kryterium (kolejność alfabetyczna, długość imienia), żeby wybrać akurat
    Michała Doryckiego.

    Sprawa ma się podobnie do miejsc w rankingu w danych zawodach, jeśli 2 osoby mają po 1000 pkt, to
    w rankingu są ex aeqo.

    Wydaje mi się, że należy złączyć podaną tabelę z nią samą, tylko nie znakiem "=", a ">", natomiast tutaj kończy się moja intuicja, która mogłaby doprowadzić do poprawnego rozwiązania.

    Byłbym wdzięczny za pomoc w znalezieniu rozwiązania.

    Pozdrawiam, Wiktor : )

    • Cześć Wiktor! :)
      Mimo że wpis jest z 2013 roku, czyli ma całe 7 lat, to zapytanie spełnia założenia, które brzmią "chciałbym wybrać z tej tabeli wiek osoby która jest młodsza od najstaszej osoby ale starsza od pozostałych osób.". A w odniesieniu tego co piszesz to ja tutaj wybieram tylko wiek a ten dla osób które mają ten sam wiek, jest, co jest oczywiste - ten sam.

      To co Ty potrzebujesz to nieco inny problem, ciężko mi pomóc konkretną sqlką bo tę wyżej pisałem w MsSql którego już nie używam, ale np. dla MySql'a mogłby to wygląda tak:

      SELECT * from MyGuests where wiek = (SELECT wiek from MyGuests order by wiek limit 1 offset 1)

      Mam nadzieję że to naprowadzi na rozwiązanie.

      Pozdrawiam!

      • Faktycznie, po tym jak Pan odpisał jeszcze raz przeczytałem dokładnie o czym jest wpis na blogu. Generalnie mój problem brzmiał "Wybrać dane osób młodszych od najstarszej osoby, ale też starszych od reszty". Problem został rozwiązany i jeśli to może się komuś przydać wrzucam zapytanie, które robi ranking uzwględniający miejsca ax aeqo:

        [ 1 Sposób ]
        SELECT wiek, imie, nazwisko
        FROM Osoby O
        WHERE (SELECT COUNT(DISTINCT wiek) FROM Osoby WHERE wiek > O.wiek) = 1;

        [ 2 Sposób ]
        SELECT A.wiek, A.imie, A.nazwisko, COUNT(DISTINCT B.wiek)
        FROM Osoby A
        LEFT JOIN Osoby B ON A.wiek < B.wiek
        GROUP BY A.wiek, A.imie, A.nazwisko
        HAVING COUNT(DISTINCT B.wiek) = 1

        Usuwając HAVING z drugiego sposobu otrzymujemy pełny ranking osób w zależności od wieku. Jako, że może się to przydać innym może warto zrobić z tego osobny atrykuł? :)

Ostatnie wpisy

Podsumowanie: luty i marzec 2024

Ostatnio tygodnie były tak bardzo wypełnione, że nie udało mi się napisać nawet krótkiego podsumowanie. Więc dziś zbiorczo podsumuję luty… Read More

3 tygodnie ago

Podsumowanie: styczeń 2024

Zapraszam na krótkie podsumowanie miesiąca. Książki W styczniu przeczytałem "Homo Deus: Historia jutra". Książka łudząco podoba do wcześniejszej książki tego… Read More

3 miesiące ago

Podsumowanie roku 2023

Cześć! Zapraszam na podsumowanie roku 2023. Książki Zacznijmy od książek. W tym roku cel 35 książek nie został osiągnięty. Niemniej… Read More

4 miesiące ago

Podsumowanie: grudzień 2023

Zapraszam na krótkie podsumowanie miesiąca. Książki W grudniu skończyłem czytać Mein Kampf. Nudna książka. Ciekawsze fragmenty można by było streścić… Read More

4 miesiące ago

Praca zdalna – co z nią dalej?

Cześć, ostatnio w Internecie pojawiło się dużo artykułów, które nie były przychylne pracy zdalnej. Z drugiej strony większość komentarzy pod… Read More

4 miesiące ago

Podsumowanie: listopad 2023

Zapraszam na krótkie podsumowanie miesiąca. Książki W listopadzie dokończyłem cykl "Z mgły zrodzony" Sandersona. Tylko "Stop prawa" mi nie do… Read More

5 miesięcy ago