简体   繁体   中英

Propel2 joining with the table and then grouping by with aggregate function

I have two tables: food(id, name), review(user_id, food_id, rating). Now I want to join food table with review table and add virtual column to the food table with name avg_rating, that will obviously hold value of average rating of the food based on the reviews. So my idea was to do something like this:

$food = FoodQuery::create()
        ->filterById(15) // constant for testing purposes only
        ->leftJoinWithReview()
        ->withColumn("AVG(review.rating)", "avg_rating")
        ->groupBy("review.rating")
        ->find()

Now in debugger I see this:

result = {Propel\Runtime\Collection\ObjectCollection} [7]
 index = {array} [1]
 indexSplHash = {array} [1]
 model = "Food"
 fullyQualifiedModel = \Food
 formatter = {Propel\Runtime\Formatter\ObjectFormatter} [10]
 data = {array} [1]
  0 = {\Food} [34]
   new = false
   deleted = false
   modifiedColumns = {array} [0]
   virtualColumns = {array} [1]
    avg_rating = "5.0000"
   id = 15
   name = "Salát Caesar"
   collReviews = {Propel\Runtime\Collection\ObjectCollection} [7]
    index = {array} [2]
    indexSplHash = {array} [2]
    model = "Review"
    fullyQualifiedModel = "\Review"
    formatter = null
    data = {array} [2]
     0 = {\Review} [14]
      new = false
      deleted = false
      modifiedColumns = {array} [0]
      virtualColumns = {array} [0]
      user_id = 1
      food_id = 15
      rating = 3
      aFood = {\Food} [34]
      aUser = null
      alreadyInSave = false
      reviewThumbsUpsScheduledForDeletion = null
     1 = {\Review} [14]
      new = false
      deleted = false
      modifiedColumns = {array} [0]
      virtualColumns = {array} [0]
      user_id = 3
      food_id = 15
      rating = 5
      aFood = {\Food} [34]
      aUser = null
      alreadyInSave = false
      reviewThumbsUpsScheduledForDeletion = null
    *Propel\Runtime\Collection\Collection*pluralizer = null
   collReviewsPartial = false
   alreadyInSave = false
   reviewsScheduledForDeletion = null
 *Propel\Runtime\Collection\Collecti4

Problem is that average rating is not correct. In virtualColumns you can see avg_rating field with value "5.0000". But when you look little bit lower you can actually see that this food has 2 reviews with rating 3 and 5, so the average should be value "4.0000".

Where is the problem? Why is this not working correctly?

You are currently doing a left join on the review table. Left joining will result in several rows being returned (one per review). For each row returned, there is only one review, so the 'average' will be the same as the review score for that row. Grouping by the average will not do much, it will only group reviews with the exact same score, and that is not what you are looking for.

You should group by your food id first. Then you will be able to get a single row per food item, with an average review score.

$food = FoodQuery::create()
    ->filterById(15) // constant for testing purposes only
    ->groupById()
    ->leftJoinWithReview()
    ->withColumn("AVG(review.rating)", "avg_rating")
    ->find();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM