TSQLORderByTop_00

Porządkowanie wyników z wykorzystaniem ORDER BY i TOP

 

Artykuł ten jest częścią serii Od 0 do TSQL, którą znajdziesz tutaj.

W ostatnim artykule rozszerzyliśmy sobie wiedzę na temat filtrowania przy pomocy klauzuli WHERE oraz predykatów logicznych, słów kluczowych BETWEEN oraz LIKE. Jednak za każdym razem gdy dostawaliśmy określone dane w rezultacie nie były one w żaden sposób uporządkowane. Niejednokrotnie otrzymany rezultat może wydawać się uporządkowany lecz możemy to traktować jako przypadek, gdyż aby mieć pewność co do porządku danych w zwracanym rezultacie musimy użyć specjalnej klauzuli tj. ORDER BY, która będzie tematem niniejszej publikacji.

Tak więc klauzula ORDER BY służy do porządkowania danych w ramach określonego zapytania. Podstawowa składnia z użyciem ORDER BY została przedstawiona poniżej.

SELECT
	Fields
FROM
	Table_name
WHERE
        Expressions
ORDER BY
        Fields ASC/DESC

Jak można zauważyć w ramach ORDER BY definiujemy pola po których chcemy sortować nasz rezultat. O kierunku sortowania decyduje słowo kluczowe ASC oznaczające kierunek rosnący oraz DESC oznaczające kierunek malejący. Definicja kierunku porządkowania jest opcjonalna – w momencie gdy ich nie podamy dane porządkowane są rosnąco. Zobrazujemy te możliwości wykorzystując standardowo tabelę Employees w bazie Northwind.

SELECT
	FirstName,
	LastName,
        Title
FROM
	Employees
ORDER BY
	LastName ASC

W rezultacie otrzymamy uporządkowany zestaw po nazwisku. Ten sam efekt otrzymalibyśmy bez użycia słowa kluczowego ASC, warto jednak stosować ASC i DESC dla przejrzystości stosowanego kodu.

Result

Co jeżeli chcemy sortować po więcej niż jednej kolumnie? Oczywiście jest to możliwe – posortujemy  dane malejąco po stanowisku, a następnie rosnąco po Nazwisku.

SELECT
	FirstName,
	LastName,
	Title
FROM
	Employees
ORDER BY
	Title DESC,LastName ASC

Result

Jak widać porządkowanie po kilku kolumnach jest bardzo proste. Jednak powyższe przykłady nie wyczerpują możliwości ORDER BY. Istotne jest to, że w ramach ORDER BY (w przeciwieństwie do sekcji WHERE) możemy używać aliasów, które nadaliśmy w sekcji SELECT. Tak więc podążając tym tokiem myślenia spójrzmy na poniższy przykład – jak widać, mimo użycia aliasu rezultat jest prawidłowy.

SELECT
	FirstName,
	LastName AS Surname,
	Title
FROM
	Employees
ORDER BY
	Title DESC,Surname ASC

Result

Używanie aliasów w ORDER BY jest możliwe ze względu na fakt, iż klauzula ta jest wykonywana po klauzuli SELECT, a więc po nadaniu polom aliasów.

Z omawianą sekcją zapytania związany jest jeszcze jeden fakt, otóż zamiast jawnie używać nazw pól lub aliasów, możemy podać numer kolumny po której chcemy porządkować.

SELECT
	FirstName,
	LastName AS Surname,
	Title
FROM
	Employees
ORDER BY
	2 DESC,3 ASC

Result

Używanie numerów kolumn jest jednak czymś czego powinniśmy unikać podobnie jak używanie SELECT *. Dopuszczalne jest użycie numerów kolumn w ORDER BY podczas testowania zapytań lub np. podczas zapytań ad-hoc kierowanych do bazy.

Drugim słowem kluczowym opisywanym w ramach dzisiejszego artykułu jest słowo TOP.  Jest ono powiązane z ORDER BY i służy limitowaniu rezultatu. Limitowanie to polega na posortowaniu danych według określonych warunków i wybranie pierwszych N rekordów. Dla lepszego zrozumienia zobrazujmy to określonym przykładem w którym użyjemy tabeli Produktów.

SELECT 
  TOP 11
	[ProductID],
	[UnitPrice]
FROM
	[Products]
ORDER BY
	[UnitPrice] DESC

Powyższe zapytanie zwróci 11 produktów o najwyższych cenach. SQL Server wykonując powyższe zapytanie najpierw uporządkował cały zestaw danych sortując go malejąco po cenie, a następnie wybrał pierwsze 11 rekordów.

Result

Zwróćcie uwagę, iż limitowanie rezultatu według warunku sortowania jest bardzo proste w implementacji. Co natomiast jeżeli kolejne rekordy nie uwzględnione w finalnym rezultacie mają te samą cenę co produkt o identyfikatorze 27? Możemy również zawrzeć je w rezultacie dodając do klauzuli TOP słowa kluczowe WITH TIES tak jak zostało to pokazane poniżej:

SELECT 
  TOP 11 WITH TIES
	[ProductID],
	[UnitPrice]
FROM
	[Products]
ORDER BY
	[UnitPrice] DESC

dzięki temu nasz rezultat uwzględnia 11 produktów o najwyższej cenie, a jeżeli są jeszcze inne produkty, które posiadają tę samą cenę co produkt na miejscu 11 to one również zostaną dodane do rezultatu.

Result

Możecie zauważyć, iż zapytanie odwoływało się do 11 produktów to rezultat zawiera ich 12 ze względu na to, iż produkt na miejscu 12 ma tą samą cenę co produkt na miejscu 11.

Zdarza się, że nie chcemy zwrócić określonej liczby wierszy, a procent wierszy całej tabeli. Na przykład załóżmy, że nie znamy liczby wierszy w tabeli Produktów, a chcemy zwrócić 10 procent najdroższych produktów. Możemy to osiągnąć używając klauzuli TOP 10 PERCENT tak jak zostało to przedstawione poniżej:

SELECT 
  TOP 10 PERCENT
	[ProductID],
	[UnitPrice]
FROM
	[Products]
ORDER BY
	[UnitPrice] DESC

Result

Oczywiście używając TOP n PERCENT możemy również dodać WITH TIES aby rozszerzyć rezultat o rekordy zawierające tę samą cenę co rekord ostatni na liście. Mam nadzieję, że niniejszy artykuł przybliżył Wam mechanizm porządkowania rezultatów i ich limitowania za pomocą słów kluczowych ORDER BY i TOP. W następnym epizodzie zajmiemy się słowami kluczowymi CASE oraz IIF – Zapraszam!

Spis dostępnych artykułów w ramach sesji znajdziesz tutaj.

4 Comments

  1. Witam
    Czy mógłby mi Pan pomóc jak wpisuję komendę SELECT TOP 5 WITH TIES *
    FROM Employee
    Order by Salary DESC pojawia mi się komunikat “Instrukcja SELECT zawiera niepoprawnie napisane albo błędne słowo zastrzeżone albo argument, bądź też zastosowano niewłaściwe znaki przestankowe. Komenda bez słowa with ties działa bez problemu. Pracuje na accessie 2016 czy może ta komenda nie występuje w tej wersji Accessa

    • Cześć! Obawiam się, że “WITH TIES” nie jest częścią języka SQL wbudowanego w Accessa. Rozwiązaniem problemu może być użycie podzapytań.

  2. Witam,
    Jak można uzyskać efekt wprowadzania danych do tabeli jak w rejestrze przesuwnym?:
    tak aby najnowsza wartość była zawsze “on top” i była zawsze definiowana przez id=1
    poniżej przykład w krokach 1,2,3 i 4
    1) id=1 ,value1

    2) id=1, value2
    id=2, value1

    3) id=1, value3
    id=2, value2
    id=3,value1

    4) id=1, value4
    id=2, value3
    id=3,value2
    id=4,value1

    • Witam,
      jeśli wartość samego identyfikatora nie jest ważna ale najważniejsze jest aby najnowsza wartość zawsze miała najniższy identyfikator to można np. użyć właściwości IDENTITY zdefiniowanej przy tworzeniu tabeli:
      CREATE TABLE dbo.Test
      (
      ID BIGINT IDENTITY(10,-1),
      Value DECIMAL(18,2)
      )
      GO
      Dzięki temu każdy kolejny wiersz dostanie identyfikator o 1 mniejszy niż poprzedni.
      O IDENTITY napisałem kiedyś parę słów, artykuł znajdzie Pan tutaj: https://pl.seequality.net/identity/

      Pozdrawiam!

Leave a Reply