Jak zrobić bąbelki czyli ORDER BY po domowemu.



W jednym z projektów kolega pracował nad funkcją "słownikową".  Funkcja ta miała za zadanie pobrać rekordy z tabeli konfiguracyjnej i zapisać je w porządku posortowanym do tablicy asocjacyjnej.  Zadanie wydawałoby się proste.
Ot zwykłe:
select * 
bulk collect into Tablica 
from Tabela 
ORDER by kolumna.
Czekałam kilka dni. Ale nic. Przypominałam się - "Pracuję nad tym!". Zachodziłam w głowę, cóż tam za problem się pojawił, że tyle to trwa? I w końcu jest! Funkcja gotowa do code review.
Siadam, paczę.
Nie wierzę.
Zamiast dosłownie kilku linijek kodu mam ich kilkadziesiąt!
Ale czemu?
Otóż po chwili analizy odkryłam, że kolega porzucił stare dobre ORDER BY i zaimplementował własne sortowanie. Bąbelkowe....

Doceniam pracę i wiedzę. Niemniej mało co mnie tak irytuje jak komplikowanie prostych spraw! Także sortowanie bąbelkowe wyleciało z hukiem i ORDER BY został przywrócony.

Ale w sumie sobie pomyślałam, że nigdy nie napisałam żadnego sortowania. Stwierdziłam więc, że spróbuję. Kolega spędził nad tym dobry tydzień więc przyszykowałam sobie prowiant, kawę,  herbatę, poduszkę.
I wszystko na nic. 15 minut zabawy, to wszystko co algorytm sortowania bąbelkowego ma do zaoferowania.

PRÓBNY ALGORYTM
set serveroutput on
declare

type tabNum is table of number index by pls_integer;
tNum tabNum;

nTabCnt number;
nCurVal number;
nNextVal number;

begin

tnum(1) := 3;
tnum(2) := 2;
tnum(3) := 1;

nTabCnt := tNum.count;

for z in 1..nTabCnt-1 loop

    for i in 1..nTabCnt-1 loop
        nCurVal :=tnum(i);
        nNextVal := tNum(i+1);
        
        if nCurVal > nNextVal then
           tnum(i) :=   nNextVal;
           tnum(i+1) := nCurVal;
        end if;
    
    end loop;
    
end loop;

for z in 1..nTabCnt loop
    dbms_output.put_line(z || ' ' || tnum(z));
end loop;

end;

Select z tabeli HR.EMPLOYEES
set serveroutput on
declare

type tabNum is table of number index by pls_integer;
tNum tabNum;

nTabCnt number;
nCurVal number;
nNextVal number;

begin

tnum(1) := 3;
tnum(2) := 2;
tnum(3) := 1;

nTabCnt := tNum.count;

for z in 1..nTabCnt-1 loop

    for i in 1..nTabCnt-1 loop
        nCurVal :=tnum(i);
        nNextVal := tNum(i+1);
        
        if nCurVal > nNextVal then
           tnum(i) :=   nNextVal;
           tnum(i+1) := nCurVal;
        end if;
    
    end loop;
    
end loop;

for z in 1..nTabCnt loop
    dbms_output.put_line(z || ' ' || tnum(z));
end loop;

end;

W sumie fajna zabawa. Tylko krótka :D


Komentarze