Pchełki SQL: Krawaty górą

Zaczniemy od wyjaśnienia tytułu dzisiejszego wpisu. „krawat” to po angielsku „tie”, słówko z wieloma znaczeniami.

Efekt: głupi tytuł wpisu. Ale tylko tytuł, bowiem dalej robi się ciekawie.

W pierwszej części autor tłumaczy tytuł wpisu.

W drugiej zaś…

Do dzieła!

Wyobraźmy sobie, że mamy zdenormalizowaną tabelę wyników w jakiejś bliżej nieokreślonej dziedzinie sportowej. Chcemy sprawdzić, kto wygrał, a także, jak wygląda kolejność poszczególnych zawodników:

IF OBJECT_ID('tempdb..#wyniki') IS NOT NULL
DROP TABLE #wyniki;
WITH cte1 AS (
SELECT 'Jan Kowalski' osoba, 18 wynik
UNION ALL SELECT 'Jan Malinowski', 23
UNION ALL SELECT 'Barbara Klumpf', 16
UNION ALL SELECT 'Hubert Grzyb', 19
UNION ALL SELECT 'Aniela Chytry', 37
UNION ALL SELECT 'Kalina Szyszka', 92
UNION ALL SELECT 'Grzegorz Grzelichowski', 37
UNION ALL SELECT 'Alojzy Babel', 76
)
SELECT * INTO #wyniki FROM cte1;

SELECT * FROM #wyniki
ORDER BY wynik DESC;

Wynik powyższego zapytania wygląda tak:

osoba wynik
Kalina Szyszka 92
Alojzy Babel 76
Aniela Chytry 37
Grzegorz Grzelichowski 37
Jan Malinowski 23
Hubert Grzyb 19
Jan Kowalski 18
Barbara Klumpf 16

Na razie wszystko jasne. Mamy listę zawodników, posortowaną malejąco według wyników. Wygrała pani Kalina, za nią na drugim miejscu jest pan Alojzy, a trzecie miejsce ex aequo należy do pani Anieli i pana Grzegorza.

Załóżmy teraz, że chcemy wyłonić trzech najlepszych zawodników, żeby ich postawić na podium.

Pierwsze i drugie miejsca – sprawa jest oczywista. Ale kogo postawić na miejscu trzecim?

Jeżeli damy tam pana Grzegorza, wrzask podniosą feministki. Jeżeli panią Anielę, zostaniemy posądzeni o rasizm (pan Grzegorz, choć tak nie brzmi, jest czarny jak sfera Schwarzschilda). Wypadałoby zbudować specjalne podium czteroosobowe… Tylko jak zmusić SQL-a, żeby w takiej sytuacji nikogo nie faworyzował? No bo tak:

IF OBJECT_ID('tempdb..#wyniki') IS NOT NULL
DROP TABLE #wyniki;

WITH cte1 AS (
SELECT 'Jan Kowalski' osoba, 18 wynik
UNION ALL SELECT 'Jan Malinowski', 23
UNION ALL SELECT 'Barbara Klumpf', 16
UNION ALL SELECT 'Hubert Grzyb', 19
UNION ALL SELECT 'Kalina Szyszka', 92
UNION ALL SELECT 'Grzegorz Grzelichowski', 37
UNION ALL SELECT 'Aniela Chytry', 37
UNION ALL SELECT 'Alojzy Babel', 76
)
SELECT * INTO #wyniki FROM cte1;

SELECT TOP 3 * FROM #wyniki
ORDER BY wynik DESC;

W wyniku dostajemy:

osoba wynik
Kalina Szyszka 92
Alojzy Babel 76
Grzegorz Grzelichowski 37

Ale już:

IF OBJECT_ID('tempdb..#wyniki') IS NOT NULL
DROP TABLE #wyniki;

WITH cte1 AS (
SELECT 'Jan Kowalski' osoba, 18 wynik
UNION ALL SELECT 'Jan Malinowski', 23
UNION ALL SELECT 'Barbara Klumpf', 16
UNION ALL SELECT 'Hubert Grzyb', 19
UNION ALL SELECT 'Kalina Szyszka', 92
UNION ALL SELECT 'Aniela Chytry', 37
UNION ALL SELECT 'Grzegorz Grzelichowski', 37
UNION ALL SELECT 'Alojzy Babel', 76
)
SELECT * INTO #wyniki FROM cte1;

SELECT TOP 3 * FROM #wyniki
ORDER BY wynik DESC;

Daje na wyjściu:

osoba wynik
Kalina Szyszka 92
Alojzy Babel 76
Aniela Chytry 37

Jak widać, SQL Server działa tu na zasadzie „kto pierwszy, ten lepszy” i na trzecim miejscu umieszcza osobę, która jako pierwsza była wstawiona do tabeli wyników.

Co więc robić, panie premierze?

Odpowiedź jest prosta: KRAWATY!

Trzeba wybrać osoby z krawatami!

O, tak:

IF OBJECT_ID('tempdb..#wyniki') IS NOT NULL
DROP TABLE #wyniki;

WITH cte1 AS (
SELECT 'Jan Kowalski' osoba, 18 wynik
UNION ALL SELECT 'Jan Malinowski', 23
UNION ALL SELECT 'Barbara Klumpf', 16
UNION ALL SELECT 'Hubert Grzyb', 19
UNION ALL SELECT 'Kalina Szyszka', 92
UNION ALL SELECT 'Aniela Chytry', 37
UNION ALL SELECT 'Grzegorz Grzelichowski', 37
UNION ALL SELECT 'Alojzy Babel', 76
)
SELECT * INTO #wyniki FROM cte1;

SELECT TOP 3 WITH TIES * FROM #wyniki
ORDER BY wynik DESC;

Dodanie klauzuli „WITH TIES” da nam na wyjściu cztery rekordy:

osoba wynik
Kalina Szyszka 92
Alojzy Babel 76
Aniela Chytry 37
Grzegorz Grzelichowski 37

Używam SQL-a od tak dawna, że czasem mi się myli i zamiast normalnie poprosić Żonę o widelec z szafki, mówię do niej SELECT widelec FROM szafka. Przerażające jest, że ona to rozumie, ale to temat na kiedy indziej 😉 W każdym razie chcę powiedzieć, że sądziłem, iż wszystkie zakamarki komendy SELECT są mi już dobrze znane. Tymczasem proszę – WITH TIES.

Dziwny świat.

Ha!

Autor: xpil

Po czterdziestce. Żonaty. Dzieciaty. Komputerowiec. Krwiodawca. Emigrant. Rusofil. Lemofil. Sarkastyczny. Uparty. Mól książkowy. Ateista. Apolityczny. Nie oglądam TV. Uwielbiam matematykę. Walę prosto z mostu. Gram na paru instrumentach. Lubię planszówki. Słucham bluesa, poezji śpiewanej i kapel a'capella. || Kliknij tutaj po więcej szczegółów ||

Dodaj komentarz

3 komentarzy do "Pchełki SQL: Krawaty górą"

Powiadom o
avatar
Sortuj wg:   najnowszy | najstarszy | oceniany
Butter
Gość

po kiego grzyba używasz #tabel skoro masz cte?

Butter
Gość

dodatkowo, zapytanie zadziałało poprawnie [to bez krawata] – chciałeś 3 pierwsze rekordy. Do celów o których piszesz powinno się używać RANK

wpDiscuz