Ucząc i prowadząc szkolenia dość często spotykam się z pytaniami o to, co będzie na rozmowie kwalifikacyjnej. Postanowiłem, że napiszę o tym tutaj, aby każdy miał dostęp do tej wiedzy. Jeśli trafiło Ci się pytanie, którego tutaj nie ma, to napisz je proszę w komentarzu lub mailu do mnie na adres krystian małpa geek-on.pl. W nawiasach podałem informację na jakim poziomie zaawansowania pojawiają się takie pytania. Zaczniemy od baz danych 🙂
Prawie na każdej rozmowie od stażysty, po mid dewelopera spotykałem się (lub moi uczniowie i znajomi) z napisaniem zapytania z łączeniem tabel i grupowaniem danych. Polecam to sobie dokładnie przećwiczyć przed rozmową.
Różnica między WHERE, a HAVING
Jedno i drugie służy do filtrowania, przy czym WHERE do wierszy, a HAVING do grup. Wybranie produktów sprzedanych w marcu, pracowników zatrudnionych w 2016 roku albo produktów droższych niż 100zł, to będzie WHERE. Jeśli porównujemy do jakiegoś agregatu (sumy, średniej, ilości elementów…) to użyjemy tego w HAVING, np. miesiące, w których dokonano więcej niż 100 zakupów (count) i dział, w którym zarabia się średnio więcej niż 3000zł (avg). Bardzo ważne jest też to, że w WHERE nie możemy używać funkcji agregujących, ponieważ sprawdzamy tam warunek dla pojedynczego wiersza, HAVING za to działa na grupach (koniecznie musi pojawić się GROUP BY przed HAVINGiem), więc tam rzadko użyjemy innego porównania niż do wartości funkcji agregującej.
SELECT 1/3 (tylko MSSQL)
Pomijając, że większość silników zwróci błąd (zadziała to m.in. w MSSQL, inne silniki wymagają wskazania tabeli we FROM) mamy tu do czynienia z dzieleniem całkowitoliczbowym. Co to daje? Wynik będzie zaokrąglony do liczby całkowitej, więc otrzymamy 0. Jeśli chcielibyśmy otrzymać 0.3333, wystarczy jedną z liczb zamienić na zmiennoprzecinkową, czyli napisać SELECT 1/3.0. Trzeba pamiętać koniecznie o tym, że AVG na kolumnie z typem liczb całkowitych również zwróci liczbę całkowitą.
Różnica między UNION, a UNION ALL
Najważniejszą rzeczą przy operacjach na zbiorach jest to, że zmienia się kolejność wykonywania zapytania. ORDER BY wykonuje się na samym końcu na połączonych już wynikach. Różnica polega na tym, że UNION zwraca tylko unikalne wartości w wyniku (tak jakby zastosować DISTINCT) i jeśli wiersz powtórzył się nawet w ramach tego samego zapytania, to nie zostanie zwrócony w wyniku. Dodanie ALL spowoduje, że otrzymamy wszystkie wiersze.
Jakie są rodzaje złączeń
Wszystkich rodzajów złączeń jest kila, ale wystarczy znać 4, ponieważ reszta jest tylko ich wariacją:
– złączenie wewnętrzne – INNER JOIN – łączymy tylko te wiersze, które tworzą parę
– złączenie zewnętrzne lewo/prawo stronne – LEFT/RIGHT [OUTER] JOIN – bierzemy lewą lub prawą tabelę całą i dołączamy z tej drugiej tylko pasujące wiersze. Jak rozpoznać co jest z lewej/prawej strony? Jeśli zapiszemy zapytanie w jednej linijce, to tabela znajdująca się po lewej stronie JOINa (czyli przed nim) jest LEFT, natomiast ta, znajdująca się za JOINem jest RIGHT. Wszystkie wiersze, które nie znalazły dopasowania będą miały uzupełnione kolumny NULLami.
– pełne zewnętrzne złączenie – FULL OUTER JOIN – tu bierzemy obie tabele w całości. Jeśli coś znajdzie dopasowanie, to super, połączymy te wiersze. Jeśli jakiś wiersz z którejkolwiek strony nie znajdzie dopasowania, wtedy druga strona zostanie uzupełniona NULLami.
– złączenie krzyżowe/iloczyn kartezjański – CROSS JOIN – tu jest jak w Modzie Na Sukces: każdy wiersz połączy się z każdym. Z tym rodzajem złączenia trzeba uważać, ponieważ łatwo zamulić serwer przez jego nadmierne obciążenie.
Pozostałe złączenia to Self JOIN, Equi JOIN, Theta JOIN, Anti JOIN i Semi JOIN.
Krystianie, z całym szacunkiem, ale pytanie numer dwa, wykonując
select 1/3 from dual;
w Oraclu otrzymamy żądane 0,33333… i nie trzeba używać liczby zmiennoprzecinkowej w mianowniku.
Oracle akurat inaczej traktuje typy liczbowe niż MSSQL. Za słabo oznaczyłem, że pytanie dotyczy MSSQLa.
a co z niejawnym konwertowaniem ? przecież Int się przekonwertuje sam na double i wynik w MSSQL będzie zawsze 0,33333…
W Oracle się zgadzam, ale w MSSQLu nie widziałem, żeby się coś domyślnie samo konwertowało. Może coś jest zmienione w domyślnych ustawieniach?