![]() |
![]() |
![]() ![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 14 Pomógł: 0 Dołączył: 4.09.2013 Ostrzeżenie: (0%) ![]() ![]() |
Witam,
Mam problem w odpytaniu Bazy danych w sposób „elegancki”, już tłumaczę o co chodzi. Dane: (IMG:http://imageshack.com/a/img827/9602/ncvm.jpg) Zadanie: Wyszukaj pracowników zarabiających najmniej na danym etacie. Rozwiązanie, którego bym oczekiwał i uważam za eleganckie powinno mieć postać: SELECT nazwisko FROM pracownicy WHERE ( Etat , Placa_pod ) IN (SELECT Etat, MIN(Placa_pod) FROM pracownicy GROUP BY etat); Niestety nie działa ono na MS SQL. Rozwiązanie, które działa ale jest wg. mnie gorsze (nieeleganckie) ma postać: SELECT dbo.Pracownicy.Nazwisko, dbo.Pracownicy.Imie FROM dbo.Pracownicy INNER JOIN (SELECT MIN(Placa_Pod) AS Min, Etat FROM dbo.Pracownicy AS Pracownicy_1 GROUP BY Etat) AS P_1 ON dbo.Pracownicy.Placa_Pod = P_1.Min AND dbo.Pracownicy.Etat = P_1.Etat Czy któryś z szanownych forumowiczów ma pomysł na rozwiązanie bez użycia JOIN ? Z góry dziękuję Morf. Witam ponownie, po nocnych przemyśleniach: SELECT Nazwisko, Imie FROM dbo.Pracownicy AS T1 WHERE (Placa_Pod = (SELECT MIN(Placa_Pod) AS Low FROM dbo.Pracownicy WHERE (Etat = T1.Etat))) Poziom elegancji 7 / 10 i dodatkowy punkcik za bark JOIN czyli 8 /10 :-) w zasadzie jest OK chyba, że... Pozdrawiam Morf |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 14 Pomógł: 0 Dołączył: 4.09.2013 Ostrzeżenie: (0%) ![]() ![]() |
Po raz pierwszy słyszę by ktoś uznawał rozwiązanie z JOIN za mało eleganckie, a rozwiązanie z IN() za bardziej eleganckie. Bazy danych niezależnie od silnika mają metody optymalizacji JOINów tak wyśrubowane, że przy prawidłowym wykorzystaniu indeksów złączenia są najbardziej wydajnymi rozwiązaniami. W zasadzie podane "nieeleganckie rozwiązanie" jest klasyką jeśli chodzi o problemy typu szukanie minimum/maximum w grupach i działa poprawnie praktycznie we wszystkich dialektach SQL. Wprawdzie istnieją szybsze metody, ale są one dostosowane do konkretnego silnika, na przykład dla MSSQL byłoby to rozwiązanie oparte na CTE i CROSS APPLY. Ciekawi mnie czym kieruje się autor wątku oceniając elegancję, bo z pewnością nie jest to wydajność, a i czytelność też raczej nie, bo widząc GROUP BY w podzapytaniu i JOIN do całej tabeli by pobrać resztę kolumn większość ludzi z jakimś doświadczeniem w SQL jest w stanie natychmiast stwierdzić co dokładnie takie zapytanie ma robić. Witam ponownie, Udało mi się przetestować oba rozwiązania: Zapytanie: SELECT Imię, Nazwisko, Zespół, Płaca FROM Testowa_1 AS T1 WHERE Płaca = (SELECT MAX(Płaca) FROM Testowa_1 AS T2 WHERE Zespół = T1.Zespół) Jest o około 10 % szybsze od zapytania: SELECT T1.Imię, T1.Nazwisko, T1.Zespół, T1.Płaca FROM dbo.Testowa_1 AS T1 INNER JOIN (SELECT Zespół, MAX(Płaca) AS Exp1 FROM dbo.Testowa_1 GROUP BY Zespół) AS T2 ON T1.Zespół = T2.Zespół AND T1.Płaca = T2.Exp1; Testowałem na MS SQL 2008 R2 Tak więc kolega pmir13 chyba nie ma jednak do końca racji... Jedno zwraca wynik po około 78s a drugie 86s (średnia 10 odpytań). Pozdrawiam Morf |
|
|
![]() ![]() |
![]() |
Aktualny czas: 8.10.2025 - 19:18 |