|
SQL - problem z zapytaniem do bazy
gummmibear - 15-10-2009 18:12
Chciałbym wyciągnąć wszystkie aktywne umowy. Na tabele z umowami składa się:l-id -id_klienta -id_projektu -data_rozpoczęcia -data_zakonczenial
Teraz jeżeli mamy taką tabelę:
|id| |id_klient| id_projekt | data_rozpoczecia | data_zakonczenia |
4 | 1 | 46 | 2009-08-24 | 2010-09-12 |
1 | 1 | 75 | 2009-03-09 | 2010-09-12 |
5 | 1 | 75 | 2009-08-24 | 2010-09-12 |
Wynikiem zapytania powinno być najświeższa umowa dla danego id_klienta i id_projektu. Czyli coś takiego:
4 | 1 | 46 | 2009-08-24 | 2010-09-12 |
5 | 1 | 75 | 2009-08-24 | 2010-09-12 |
jaqbeu - 15-10-2009 18:41
SELECT * FROM tabelazumowa WHERE id_klienta=1 AND data_rozpoczecia=(SELECT MAX(data_rozpoczecia) FROM tabelazumowa);
W Twoim przykładzie nr. projektów są różne, ale w razie czego dodasz sobie jeszcze jedno AND i Ci wybierze co chcesz.
gummmibear - 15-10-2009 19:08
jaqbeu
Chodzi mi o wyciągnięcie wszystkich aktywnych umów które znajdują się w bazie. I ich data rozpoczęcia jest <= daty dzisiejszej. Jeżeli mamy dwie podpisane umowy dla tego samego klienta i projektu wybieramy tą z późniejszą datą.
W przypadku
|id| |id_klient| id_projekt | data_rozpoczecia | data_zakonczenia |
14| 12 | 36 | 2009-05-24 | 2010-09-12 |
4 | 12 | 36 | 2009-08-24 | 2010-09-12 |
1 | 1 | 75 | 2009-03-09 | 2010-09-12 |
5 | 1 | 75 | 2009-08-24 | 2010-09-12 |
6 | 4 | 46 | 2009-08-24 | 2010-09-12 |
7 | 13 | 25 | 2009-03-09 | 2010-09-12 |
Wynikiem zapytania powinno być
4 | 12 | 36 | 2009-08-24 | 2010-09-12 |
5 | 1 | 75 | 2009-08-24 | 2010-09-12 |
6 | 4 | 46 | 2009-08-24 | 2010-09-12 |
7 | 13 | 25 | 2009-03-09 | 2010-09-12 |
Jakoś nie mogę tego zapytania ogarnąć ;[
ziecio - 16-10-2009 00:08
Normalnie tak mnie tym zadaniem zaciekawiłeś, że spędziłem ponad 1,5h żeby to rozgryźć, niestety nie dałem rady i z determinacji znalazłem na google. A rozwiązanie jest takie: SELECT * FROM umowy INNER JOIN(SELECT max(`data_rozpoczecia`) as MaxDate, `id_klienta` FROM umowy GROUP BY `id_klienta`) as g ON (umowy.`id_klienta`=g.`id_klienta`) AND (umowy.`data_rozpoczecia`=g.MaxDate)
Ister - 16-10-2009 09:17
Odpowiedź jest niepełna - nie uwzględnia sytuacji, w której jeden klient ma umowę na kilka projektów. Nie uwzględnia też umów już zakończonych i jeszcze nie rozpoczętych. Ja bym to uzupełnił tak:
SELECT u.* FROM umowy AS u INNER JOIN ( SELECT max('data_rozpoczecia') AS MaxDate, 'id_klient', 'id_projekt' FROM umowy WHERE now() BETWEEN 'data_rozpoczecia' AND 'data_zakonczenia' GROUP BY 'id_klient','id_projekt' ) AS g ON (u.'id_klient'=g.'id_klient') AND (u.'id_projekt'=g.'id_projekt') AND (u.'data_rozpoczecia'=g.MaxDate)
a żeby nie było, że tylko z gotowych rozwiązań korzystam, to wcześniej pokombinowałem i wyprodukowałem coś takiego, podejrzewam, że wydajnościowo słabsze, ale też powinno zadziałać (dla wygody pomijam wszystkie 'uszy' w nazwach tabel i kolumn:
SELECT * FROM umowy WHERE now() BETWEEN data_rozpoczecia AND data_zakonczenia AND id NOT IN ( SELECT u1.id FROM umowy u1 JOIN umowy u2 ON u1.id_klient=u2.id_klient AND u1.id_projekt=u2.id_projekt AND u1.data_zakonczenia<u2.data_zakonczenia WHERE now() BETWEEN u1.data_rozpoczecia AND u1.data_zakonczenia AND now() BETWEEN u2.data_rozpoczecia AND u2.data_zakonczenia )
Cóż, wymyślenie tego rozwiązania zajęło mi nie więcej niż pół godziny...
[ Dodano: 2009-10-16, 09:19 ] Jeszcze jedno - nie napisałeś w jakiej bazie danych jesteśmy. Oba powyższe rozwiązania działać powinny w każdej bazie SQLowej. Natomiast w Oracle'u można napisać eleganckie zapytanie zagnieżdżone. Przynajmniej tak mi się wydaje, bo szczerze mówiąc nie chce mi się dokładnie rozpisywać trzeciej już wersji.
zanotowane.pldoc.pisz.plpdf.pisz.plminister.pev.pl
|