SQL - problem z zapytaniem do bazy

Potrzebujesz pomocy z C, C++, perl, python, itp.
gummmibear
Posty: 35
Rejestracja: 02 stycznia 2009, 08:42

SQL - problem z zapytaniem do bazy

Post autor: gummmibear »

Chciałbym wyciągnąć wszystkie aktywne umowy.
Na tabele z umowami składa się:
  • -id
    -id_klienta
    -id_projektu
    -data_rozpoczęcia
    -data_zakonczenia
Teraz jeżeli mamy taką tabelę:

Kod: Zaznacz cały

|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:

Kod: Zaznacz cały

4 | 1 | 46 | 2009-08-24 | 2010-09-12 |

5 | 1 | 75 | 2009-08-24 | 2010-09-12 |
Awatar użytkownika
jaqbeu
Posty: 57
Rejestracja: 03 lutego 2009, 15:55
Lokalizacja: Warszawa

Post autor: jaqbeu »

Kod: Zaznacz cały

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
Posty: 35
Rejestracja: 02 stycznia 2009, 08:42

Post autor: gummmibear »

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

Kod: Zaznacz cały


|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ć

Kod: Zaznacz cały



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
Posty: 86
Rejestracja: 10 kwietnia 2007, 11:58

Post autor: ziecio »

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:

Kod: Zaznacz cały

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
Junior Member
Posty: 566
Rejestracja: 05 marca 2009, 12:42

Post autor: Ister »

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:

Kod: Zaznacz cały

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:

Kod: Zaznacz cały

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.
ODPOWIEDZ