[Postgre] Zapytanie.

0

Witam.
Moje doświadczenie z SQL to raptem tydzień intensywnej nauki.
Mam problem z opracowaniem pewnego zapytania ( używam PostgreSQL 8.3.5 ).

W mojej bazie ( filmoteka ) znajdują się takie oto 3 tabele:

CREATE SEQUENCE film_sekwencja START 1;

CREATE TABLE film(
	IdFilmu integer PRIMARY KEY DEFAULT nextval('film_sekwencja'),
	Nazwa varchar(128) NOT NULL,
	DataDodania TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
	IdUzytkownika integer NOT NULL,	-- id usera który DODAŁ film do bazy
);


CREATE SEQUENCE uzytkownik_sekwencja START 1;

CREATE TABLE uzytkownik(
	IdUzytkownik integer PRIMARY KEY DEFAULT nextval('uzytkownik_sekwencja'),
	Nick varchar(24) NOT NULL,
	DataDodania DATE DEFAULT CURRENT_DATE
);


CREATE SEQUENCE ocena_sekwencja START 1;

CREATE TABLE ocena(
	IdOcena integer PRIMARY KEY DEFAULT nextval('ocena_sekwencja'),
	Ocena integer,
	IdFilmu integer NOT NULL,
	IdUzytkownika integer NOT NULL	-- id usera, który OCENIŁ film
);

Mam również zapytanie, które wyświetla:
nazwę, średnią ocenę i datę dodania filmu oraz nick usera, który dodał film do bazy:

SELECT f.nazwa,  
	round(avg(o.ocena),2) AS "Średnia ocena", 
	f.datadodania, 
	u.nick AS "Dodał"
FROM film f
JOIN uzytkownik u ON f.iduzytkownika = u.iduzytkownik
JOIN ocena o ON f.idfilmu = o.idfilmu
GROUP BY f.nazwa, 
		u.nick, 
		f.datadodania, 
		o.idocena
ORDER BY f.datadodania, 
		f.nazwa; 

Chciałbym teraz do wyniku poprzedniego zapytania dołożyć kolumnę "twoja ocena", która
wyświetli jaką ocenę dany użytkownik wystawił poszczególnym filmom, lub NULL, jeżeli
użytkownik nie wystawił jeszcze oceny dla danego filmu. Oczywiście muszę wtedy dodać

WHERE o.iduzytkownika = numer_uzytkownika_ktoremu_wypiszemy_jego_oceny.

Czli coś takiego:

nazwa Średnia ocena datadodania Dodał Twoja ocena
Psy 4.50 2008-11-23 1933.06122 RJM 3
Psy2 4.40 2008-11-23 1933.06122 Q (NULL)

Jak mam to zrobić ?

0
SELECT f.nazwa,  
        round(avg(o.ocena),2) AS "Średnia ocena", 
        f.datadodania, 
        u.nick AS "Dodał",
        x.ocena
FROM film f
JOIN uzytkownik u ON f.iduzytkownika = u.iduzytkownik
JOIN ocena o ON f.idfilmu = o.idfilmu
JOIN ocena x ON f.idfilmu = x.idfilmu and f.iduzytkownika = x.IdUzytkownika
GROUP BY f.nazwa, 
                u.nick, 
                f.datadodania, 
                x.ocena
ORDER BY f.datadodania, 
                f.nazwa; 
0

To jeszcze nie to o co chodzi.
Misiekd - twoje zapytanie zwróciło 1 rekord, taki w którym użytkownik zarówno dodał jak i ocenił film ( jego id pojawiło się w tabeli ocena i tabeli film ).

0

Zamien:
JOIN ocena x
na
LEFT JOIN ocena x

pozdrawiaMM

0

MarcinMiga - to była pierwsza rzecz jaką zrobiłem, gdy zobaczyłem, że to zapytanie nie działało.

Wynik był taki, że wypisały się wszystkie filmy, których id pojawiły się w tabeli ocena.
NULL'e w ostatniej kolumnie pojawiły się przy filmach, dla których użytkownik, który dodał film sam go nie ocenił.

Czyli z tym zapytaniem są 2 rzeczy nie tak:

I Wypisuje tylko oceny tych filmów, które zostały dodane i ocenione przez tego samego
uzytkownika ( dane iduzytkownika pojawia się w tabeli filmy oraz tabeli oceny, ja chcę
żeby wypisało wynik dla wszystkich użytkowników, nawet jeśli ich id nie pojawiło się
w tabeli film ani w tabeli oceny )

II Wypisuje tylko te filmy , które zostały kiedykolwiek ocenione ( ich id znajduje się w tabeli ocena ) Chcę wypisać wszystkie filmy, przy tych nieocenionych będzie NULL w kolumnach
średnia ocena i twoja ocena.

edit: Tu zapytanie, o którym mowa:

SELECT f.nazwa, 
        round(avg(o.ocena),2) AS "Średnia ocena",
        f.datadodania,
        u.nick AS "Dodał",
        x.ocena
FROM film f
JOIN uzytkownik u ON f.iduzytkownika = u.iduzytkownik
JOIN ocena o ON f.idfilmu = o.idfilmu
LEFT JOIN ocena x ON f.idfilmu = x.idfilmu AND f.iduzytkownika = x.IdUzytkownika
GROUP BY f.nazwa,
                u.nick,
                f.datadodania,
                x.ocena
ORDER BY f.datadodania,
                f.nazwa; 

0
SELECT 
  x.*, 
  z.ocena 
FROM
  (SELECT 
    f.idfilmu, 
    f.nazwa, 
    f.datadodania, 
    f.iduzytkownika, 
    u.nick, 
    round(avg(o.ocena), 2)
  FROM 
    film f, 
    uzytkownik u, 
    ocena o
  WHERE
    f.ikuzytkownika = u.iduzytkownika AND
    f.idfilmu = o.id_filmu
  GRROUP BY
    f.idfilmu, 
    f.nazwa, 
    f.datadodania, 
    f.iduzytkownika, 
    u.nick) x
LEFT JOIN  ocena z ON 
  x.iduzytkownika = z.iduzytkownika AND 
  x.idfilmu = z.id_filmu
ORDER BY 
  x.datadodania, 
  x.nazwa;
0

Przede wszystkim dzięki za pomoc.

Niestety to jeszcze nie jest poprawne zapytanie - zwraca takie wyniki jak to poprzednie.
Umieściłem skrypt, którym można wygenerować tabele i wypełnić je danymi w pastebin:

http://pastebin.4programmers.net/156898

0
SELECT x.*, y.ocena [twoja ocena] FROM
(
	SELECT 
		f.idfilmu, 
		Nazwa, 
		f.datadodania, 
		iduzytkownik, 
		nick, 
		avg(ocena) ocena 
	FROM 
		film f 
		JOIN uzytkownik u 
		ON 
			f.iduzytkownika=u.iduzytkownik  
		FULL JOIN ocena o 
		ON 
			o.idfilmu=f.idfilmu 
	GROUP BY 
		f.idfilmu, Nazwa, f.datadodania, iduzytkownik, nick
) x 
FULL JOIN
(
	SELECT 
		ocena, 
		idfilmu 
	FROM 
		ocena 
	WHERE 
		iduzytkownika=1
) y
ON  x.idfilmu=y.idfilmu

@misiekd: jak zrobić by ładnie pokolorował jako SQL?

// <code class="sql"> ... </code> - Cold

0

Wielkie dzięki za pomoc. To jest dokładnie to o co mi chodziło.

Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1