Radek Owczarek

Radek Owczarek Absolwent AGH

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

W tabeli Turnusy która składa sie z jednej kolumny "Data_rozpoczecia" przechowywane są daty rozpoczecia turnusów kolonijnych. Zakładając ze jeden turnus konczy sie w tym samym dniu, gdy zaczyna nastepny, oraz, że "Data_rozpoczecia" jest kluczem głównym tabeli:

1) Napisz zapytanie SQL które zwraca daty rozpoczecia i zakonczenia turnusow

2) Napisz zapytanie SQL które zwraca daty rozpoczecia i zakonczenia turnusow oraz okres trwania turnusu
Paweł Słowik

Paweł Słowik programista/analityk

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

Najprościej chyba jest coś w tym stylu( o ile dobrze zrozumiałem problem ;) )

SELECT
t.data_rozpoczecia,
s1.data_zakonczenia,
s1.data_zakonczenia-t.data_rozpoczecia AS dni
FROM
turnusy t,
(SELECT
data_rozpoczecia,
(SELECT min(data_rozpoczecia) FROM turnusy t2
WHERE t2.data_rozpoczecia>t1.data_rozpoczecia) AS data_zakonczenia
FROM turnusy t1) s1
WHERE
t.data_rozpoczecia=s1.data_rozpoczecia
ORDER BY t.data_rozpoczecia;

prawdopodobnie to nie jest optymalne rozwiązanie ale może Ci coś pomoże w dalszych poszukiwaniach ;)

pozdrawiam
Patryk K.

Patryk K. Drupal
Developer/Consultan
& Senior Software
Engineer

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

Proponuje jeszcze obliczyc ilosc dni :]

SELECT
t.data_rozpoczecia,
s1.data_zakonczenia,
DATEDIFF(s1.data_zakonczenia, t.data_rozpoczecia) AS dni
FROM
turnusy t,
(SELECT
data_rozpoczecia,
(SELECT min(data_rozpoczecia) FROM turnusy t2
WHERE t2.data_rozpoczecia>t1.data_rozpoczecia) AS data_zakonczenia
FROM turnusy t1) s1
WHERE
t.data_rozpoczecia=s1.data_rozpoczecia
ORDER BY t.data_rozpoczecia;

btw. ladnie zaplatane ale dziala :]
Paweł Słowik

Paweł Słowik programista/analityk

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

Patryk K.:Proponuje jeszcze obliczyc ilosc dni :]

DATEDIFF(s1.data_zakonczenia, t.data_rozpoczecia) AS dni



w PostgreSQL działa "-" bez potrzeby wykorzystywania funkcji ;)
Radek Owczarek

Radek Owczarek Absolwent AGH

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

Wielkie dzieki Panowie, widze ze mialem za malo podzapytan, i czesto mialem error: Subquery returns more than 1 row.
DATEDIFF jakos znalazlem :)
Z obydwu Waszych postów ulepie cos i bedzie dzialac
Pozdrawiam


Radek Owczarek edytował(a) ten post dnia 23.10.06 o godzinie 15:52

konto usunięte

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

Radek O.:Wielkie dzieki Panowie, widze ze mialem za malo podzapytan, i czesto mialem error: Subquery returns more than 1 row.
DATEDIFF jakos znalazlem :)
Z obydwu Waszych postów ulepie cos i bedzie dzialac
Pozdrawiam Radek Owczarek edytował(a) ten post dnia 23.10.06 o godzinie 15:52


na "more than 1 row" jest sposób -> group by :)
Ryszard Hapka

Ryszard Hapka Członek zarządu,
Dyrektor IT

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

Marcin B.:
Radek Owczarek:Wielkie dzieki Panowie, widze ze mialem za malo podzapytan, i czesto mialem error: Subquery returns more than 1 row.
DATEDIFF jakos znalazlem :)
Z obydwu Waszych postów ulepie cos i bedzie dzialac
Pozdrawiam Radek Owczarek edytował(a) ten post dnia 23.10.06 o godzinie 15:52


na "more than 1 row" jest sposób -> group by :)


lub limit 1 - nieco szybsze rozwiązanie ( zakładający, ze warunki zostały poprawnie skonstruowane ) :)
Marcin M.

Marcin M. Lider zespołu
programistów

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

No to może ja podam trochę bardziej "eleganckie" rozwiązanie - bez użycia podzapytań

SELECT
t1.data_rozpoczecia,
min(t2.data_rozpoczecia) as data_zakonczenia,
min(t2.data_rozpoczecia)-t1.data_rozpoczecia as dl_turnusu
FROM
turnusy t1 LEFT JOIN turnusy t2 ON (t1.data_rozpoczecia < t2.data_rozpoczecia)
GROUP BY
t1.data_rozpoczecia
ORDER BY
t1.data_rozpoczecia;

Dzięki brakowi podzapytań wykonuje się również kilkadziesiąt procent szybciej niż zaprezentowana wcześniej wersja rozwiązania.
Jeśli chcesz pozbyć się ostatniego wiersza w którym nie ma terminu zakończenia zamień LEFT JOIN na JOIN.

Analiza tego zapytania (PostgreSQL):

QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=20.00..25079.51 rows=1000 width=8) (actual time=0.060..0.156 rows=8 loops=1)
-> Nested Loop Left Join (cost=20.00..22572.00 rows=333334 width=8) (actual time=0.028..0.130 rows=29 loops=1)
Join Filter: ("outer".data_rozpoczecia Index Scan using turnusy_pkey on turnusy t1 (cost=0.00..52.00 rows=1000 width=4) (actual time=0.015..0.023 rows=8 loops=1)
-> Materialize (cost=20.00..30.00 rows=1000 width=4) (actual time=0.001..0.004 rows=8 loops=8)
-> Seq Scan on turnusy t2 (cost=0.00..20.00 rows=1000 width=4) (actual time=0.002..0.006 rows=8 loops=1)
Total runtime: 0.211 ms
(7 rows)

Time: 1,437 ms



Analiza rozwiązania poprzedniego
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Sort (cost=46831.57..46834.08 rows=1001 width=8) (actual time=0.516..0.517 rows=8 loops=1)
Sort Key: t.data_rozpoczecia
-> Hash Join (cost=22.50..46781.69 rows=1001 width=8) (actual time=0.331..0.502 rows=8 loops=1)
Hash Cond: ("outer".data_rozpoczecia = "inner".data_rozpoczecia)
-> Seq Scan on turnusy t (cost=0.00..20.00 rows=1000 width=4) (actual time=0.001..0.004 rows=8 loops=1)
-> Hash (cost=20.00..20.00 rows=1000 width=4) (actual time=0.025..0.025 rows=0 loops=1)
-> Seq Scan on turnusy t1 (cost=0.00..20.00 rows=1000 width=4) (actual time=0.007..0.011 rows=8 loops=1)
SubPlan
-> Aggregate (cost=23.34..23.34 rows=1 width=4) (actual time=0.009..0.009 rows=1 loops=8)
-> Seq Scan on turnusy t2 (cost=0.00..22.50 rows=334 width=4) (actual time=0.002..0.006 rows=4 loops=8)
Filter: (data_rozpoczecia > $0)
-> Aggregate (cost=23.34..23.34 rows=1 width=4) (actual time=0.010..0.010 rows=1 loops=8)
-> Seq Scan on turnusy t2 (cost=0.00..22.50 rows=334 width=4) (actual time=0.002..0.006 rows=4 loops=8)
Filter: (data_rozpoczecia > $0)
Total runtime: 0.611 ms
(15 rows)

Time: 2,167 ms



A więc wzrost skomplikowania zapytania a co za tym idzie także czasu wykonania - 2,167ms zamiast 1,437 ms a więc wzrost o ponad 50%. Dlatego "keep it simple" .


P.S Na co dzień mam do czynienia z bardzo dużymi bazami danych więc mam bzika na punkcie optymalizacji zapytań :)





Marcin M. edytował(a) ten post dnia 25.11.06 o godzinie 23:24
Paweł Słowik

Paweł Słowik programista/analityk

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

kapitalne !!!

Nie mogłem sobie właśnie wyobrazić jak pozbyć się tego
podzapytania, a że pisałem to zapytanie na sucho więc nawet nie próbowałem optymalizować, żeby nie skopać :)
Tomasz Maciej J.

Tomasz Maciej J. Analiza i
modelowanie
procesów,
zarządzanie
projektem, za...

Temat: Zadanie SQL, pomocy!!!!!!!!!!!!!

albo się mylę (nie patrzę teraz w books online, albo w datediff brakuje mi określenia w jakim wymiarze ma być przedstawiona różnica (d,m,w,itd).

Następna dyskusja:

[SQL Server 2014] Cykliczne...




Wyślij zaproszenie do