Java Durchschnittswert aus Datenbank ermitteln und als Rückgabewert von Java Funktion

Danny787

Ensign
Registriert
Jan. 2007
Beiträge
180
Es geht um Folgendes:

Ich versuche eine Web Applikation zu entwickeln, welche aus einer Datenbank Bücher auslesen und diese auch bewerten kann (Radiobuttons mit Werten 1-5). Die Bewertungsfunktion habe ich inzwischen implementiert, doch nun will ich noch den Durchschnittwert aller Bewertungen mittels eines SQL Befehls bestimmen und diesen als Rückgabewert definieren.

Zunächst mal den Create Befehl der Tabelle:

create table product (id int not null, author varchar(32), title varchar(256), rating int, ratingCounter int)

Die einzelnen Bewertungen (Integerwerte 1-5) werden in rating hinterlegt

Hier die Funktion, welche den Durchschnittwert ermitteln und diesen als Rückgabewert liefern soll:

public synchronized float getAverageRating(AmazonBook book){
float avgRating = 0;
try{
Statement statement = connection.createStatement();
ResultSet resultSet = statement
.executeQuery("SELECT avg(rating) FROM product WHERE title = '" + book.getTitle() + "'");

avgRating = resultSet.getFloat(1);

}catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return avgRating;
}


Eclipse schmeißt bei der Durchführung eine java.sql.SQLSyntaxErrorException

Kann mir vielleicht jemand sagen, was ich falsch mache?

Danke schon mal im Voraus :)
 
Ich gehe mal davon aus, dass das query funktioniert, wenn du manuell einen Titel darin platzierst.

Versuch mal:
Code:
PreparedStatement statement = connection.prepareStatement("[COLOR=Black]SELECT avg(rating) FROM product WHERE title = ?")[/COLOR];
statement.setString(1, [COLOR=Black]book.getTitle()[/COLOR]);
ResultSet result = statement.executeQuery();
 
Zuletzt bearbeitet:
@ Tumbleweed

Danke für deine Mühe, habs jedoch nun folgendermaßen gelöst:

Hab einfach noch nen Zähler, welcher bei jedem Rating um 1 hochgezählt wird, zusätzlich hinzugezogen und die Summe der Ratings durch diesen geteilt. Ist vielleicht nicht die eleganteste Variante, erfüllt jedoch seinen Zweck :)

public synchronized float getAverageRating(AmazonBook book){
float rating = 0;
float counter = 0;
float currentRating = 0;

try{
Statement statement = connection.createStatement();
ResultSet resultSet = statement
.executeQuery("SELECT rating, countRating from product where title = '" + book.getTitle() + "'");
while (resultSet.next()) {
currentRating = resultSet.getInt(1);
counter = resultSet.getInt(2);
}

rating = (currentRating/counter);
System.out.println(rating);

}catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return rating;

}


Dennoch Danke für deine Hilfe :)
 
Danny, ich halte die Methode von Tumbleweed für viel besser. Lass das DBMS sich um die Mittelwertberechnung kümmern. Dafür ist eine hochoptimierte Funktion schon eingebaut. Sie ist auf alle Fälle performanter, als sich jedes Rating ausgeben zu lassen, und dann den Mittelwert zu berechnen.

Btw, ich erkenne in deinem Code übrigens keine Mittelwertberechnung über alle Ratings. Die Ratings werden nicht addiert.
 
Zuletzt bearbeitet:
@ e-Laurin

Die Ratings werden in einer weiteren Funktion aufsummiert, auch der Counter wird in selbiger bei jedem Rating um 1 erhöht. Hier die Funktion:

public synchronized boolean rateBook (String bookTitle, String rating){

if (bookTitle == null && rating == null)
return false;
int intRating = Integer.parseInt(rating);

try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement
.executeQuery("SELECT rating, countRating from product where title = '" + bookTitle + "'");
while (resultSet.next()) {
int currentRating = resultSet.getInt(1);
int counter = resultSet.getInt(2);

PreparedStatement preparedStatement = connection
.prepareStatement("UPDATE product SET rating = ?,countRating = ? WHERE title = ?");

preparedStatement.setInt(1, intRating+currentRating);
preparedStatement.setInt(2, counter+1);
preparedStatement.setString(3, bookTitle);
preparedStatement.executeUpdate();
preparedStatement.close();

}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return true;


Ich wollte es ja zunächst so wie von Tumbleweed geschildet implementieren, jedoch wollte das nicht so richtig funktionieren.
Ich werd mich aber noch mal dran machen und versuchen es so zum laufen zu bekommen :)
 
Das Ganze haut generell nicht so wirklich hin. Beschäftige dich am besten mal mit Normalisierung von Datenbanken.

Sinnvolle Struktur:
Tabelle product (ID,title,author)
Tabelle rating (ref productID, datetime, rating, user?)

Abfrage wäre dann:
select avg (rating) as avgrating from rating where productID=(select top 1 id from product where title='....')

Wenn du die Struktur beibehalten willst, dann wäre deine Abfrage:
select rating/ratingcounter as avgrating from product where title='....'
 
@ WingX

Danke für deine Antwort

Mein Problem is dennoch in beiden Fällen das Selbe:

Wie kann ich den ResultSet in einen float umwandeln und diesen dann zurückgeben?

Mein Versuch mit float rating = result.getFloat(1) haut net so richtig hin, was eigentlich auch Sinn macht, da es sich hier um einen Join handelt und die Angabe eine columnIndex sinnlos ist.

Wie kann ich nun das Ergebnis des Joins durch zb. avg (rating) als Rückgabewert (float) liefern?
 
Ich denke mal, dass die DB Funktion avg() einen Double zurückliefert.
Alternativ kannst du auch erstmal einen String holen und dann auf float casten/parsen.
 
Zurück
Oben