webForumDet fria alternativet

MySQL sats problem

4 svar · 475 visningar · startad av Tibbelit

TibbelitMedlem sedan mars 200986 inlägg
#1

Hej!

Jag ska räkna ut ett medelvärde från en databas... Se uppbyggnad nedan...

Jag vill räkna ut medelvärdet av (hans, anton, fredrik, petter och cg)... Detta så att jag kan sortera filmerna efter hur vi tillsammans rankat filmerna...

Den naturliga koden jag skrev var:

SELECT *,(anton+hans+petter+fredrik+cg)/5 as medel FROM film_film ORDER BY medel DESC

Jag skapar en constrain (av alla som kan ge röster) och sedan delar jag det med antal personer... MEN nu är det så att alla inte har sett alla filmerna... Så där det bara är 4 personer som sett en film ska det ju bara delas på 4 personer.

Så jag behöver en formel el. något liknande: OM kolumnen inte är tom ska den räknas som 1 annars 0. På det sättet kan man ju räkna ut hur många summan ska delas på...

Men jag vet som sagt inte hur jag ska lösa detta, har suttit med det ett tag nu:/ Så all hjälp uppskattas verkligen!

Tack på förhand

// Tibbelit

LarsGMedlem sedan dec. 200012 464 inlägg
#2

Din datamodell är högst olämplig. Lagra ranking i en separat tabell definierad enligt

create table filmRanking(filmId int, -- foreign key till filmtabellen
 name varchar(20),
 primary key(filmId,name),
 rank int)

Om du vill kan du även ha en tabell för namn med ett id som du sedan använder i filmRanking. Det beror på om du vill lagra mer information om personen.

Lagra bara de som har sett filmen

för att beräkna medelvärdet

select film.id,
         film.title,
         avg(filmRanking.rank+0.0) as medel
  from film left join filmRanking on film.id = filmRanking.filmid
 group by film.id,
         film.title
 order by medel desc

Med din nuvarande datamodell så måste du ändra i tabelldefinitioner och frågor om det tillkomer någon som också skall bedöma en film.

nitro2k01Medlem sedan aug. 20039 342 inlägg
#3

Att lagra användardata som kolumnnamn är lite fult i min mening. Jag skulle lösa det så att man har tre tabeller: En för filmerna, en för användarna, och slutligen en med betygen. Betygen lagras då på med användarid, filmid samt betyg. Du måste med denna modell själv ansvara för att betygtabellen inte innehåller flera betyg från samma person, på samma film. (Alltså, uppdatera raden för en vissa kombination av film och användare om den redan existerar.)

Jag har gjort iordning ett litet testcase som du kan kika på. Bifogat som en fil är strukturen som jag använde samt lite testdata.

För att plocka ut datat använde jag följande:

SELECT 
  m.moviename AS moviename,
  if(AVG(r.rating) IS NULL, 'Filmen har inte betygsatts ännu', AVG(r.rating)) AS rating,
  COUNT(r.rating) AS num_reviewers,
  GROUP_CONCAT(u.reviewername ORDER BY u.reviewername ASC SEPARATOR ', ') AS reviewers
  FROM `test_movies` m
LEFT JOIN test_movierank r ON m.movieid = r.movieid
LEFT JOIN test_reviewers u ON u.reviewerid = r.reviewerid
WHERE 1
GROUP BY m.movieid

Det stora tricket är GROUP BY som plockat ut en film per rad och ändå låter dig använda aggregerande funktioner såsom AVG på varje rad som motsvarar en film.

JOIN'arna plockar ut rankning och användarnamn. Att det är en LEFT JOIN tillåter att högersidan av uttrycket så att säga kan returnera en tom mängd. (Om det inte finns några betyg för en viss film) Hade man använd INNER JOIN istället hade alla filmer utan betyg ignorerats.

AVG, COUNT och GROUP_CONCAT är alla aggregerande funktioner som utvinner saker från det hämtade datat. AVG returnerar uppebarligen medelbetyget, COUNT antalet betyg och GROUP_CONCAT slår ihop namnen på de som har betygsatt till en kommaseparerad sträng.
if(AVG(r.rating) IS NULL, 'Filmen har inte betygsatts ännu', AVG(r.rating)) AS rating är lite socker för att få skapa en anvöndarvänlig sträng. Du kan naturligtvis skriva AVG(r.rating) AS rating och då får du ut NULL-värden för filmer utan betyg.

Testfrågan har inga contraints, men du kan lägga till WHERE och ORDER BY efter behov.

Edit: LarsG hann före eftersom jag spenderade för mycket tid på att ordbajsa.

TibbelitMedlem sedan mars 200986 inlägg
#4

Tusen tack!

Tack nitro2k01!

Efter att byggt om sidan som du föreslog fungerar allt perfekt. Mitt lilla projekt är nu fullbordat och fungerar precis som det ska. Återigen tack! Verkligen trvligt att du hade tid att hjälpa mig. Även tack till LarsG som gav mig ett alternativ som skulle lösa problemet!

// Tibbelit

ZaimanMedlem sedan dec. 20014 239 inlägg
#5

Markera gärna det svar som löst ditt problem enligt http://www.webforum.nu/faq.php?faq=vb_faq#faq_faq_acceptance

135 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
133 ms — hämta tråd, inlägg och bilagor (db)