package db import ( "context" "database/sql" "fmt" ) type GetTopListLocationsParams struct { Limit int32 Offset int32 OrderBy string RegionType sql.NullInt16 } type GetTopListLocationsRow struct { RowNumber int32 `json:"row_number"` ID int32 `json:"id"` Name string `json:"name"` RegionName string `json:"region_name"` Thumbnail sql.NullString `json:"thumbnail"` Address string `json:"address"` GoogleMapsLink string `json:"google_maps_link"` RegencyName string `json:"regency_name"` CriticScore sql.NullInt32 `json:"critic_score"` CriticCount int16 `json:"critic_count"` UserScore sql.NullInt32 `json:"user_score"` UserCount int16 `json:"user_count"` TotalCount int16 `json:"total_count"` CriticBayes int16 `json:"critic_bayes"` UserBayes int16 `json:"user_bayes"` AvgBayes int16 `json:"avg_bayes"` } func (q *Queries) GetTopListLocations(ctx context.Context, arg GetTopListLocationsParams) ([]GetTopListLocationsRow, error) { regionType := "" if arg.RegionType.Valid { regionType = fmt.Sprintf("AND reg.id = %d", arg.RegionType.Int16) } getTopListQ := fmt.Sprintf(`SELECT row_number() over (ORDER BY %s DESC) as row_number, * FROM( SELECT *, (SELECT 5 * 4 + coalesce(critic_score, 0) * coalesce(critic_count, 0) / 5 + coalesce(critic_count, 0)) as critic_bayes, (SELECT 50 + coalesce(user_score, 0) * coalesce(user_count, 0) / 50 + coalesce(user_count, 0)) as user_bayes, ((SELECT 50 + coalesce(user_score, 0) * coalesce(user_count, 0) / 50 + coalesce(user_count, 0)) + (SELECT 5 * 4 + coalesce(critic_score, 0) * coalesce(critic_count, 0) / 5 + coalesce(critic_count, 0)) ) / 2 as avg_bayes FROM ( SELECT l.id, name, l.address, reg.region_name as region_name, l.google_maps_link, thumbnail, re.regency_name, (SELECT SUM(score) from reviews re where re.is_from_critic = true and re.location_id = l.id) as critic_score, (SELECT COUNT(id) from reviews re where re.is_from_critic = true and re.location_id = l.id) as critic_count, (SELECT SUM(score) from reviews re where re.is_from_critic = false and re.location_id = l.id) as user_score, (SELECT COUNT(id) from reviews re where re.is_from_critic = false and re.location_id = l.id) as user_count FROM locations l JOIN regencies re on re.id = l.regency_id JOIN provinces prov on prov.id = re.province_id JOIN regions reg on reg.id = prov.region_id WHERE approved_by IS NOT NULL %s ) iq1 ) iq2 LIMIT $1 OFFSET $2;`, arg.OrderBy, regionType) rows, err := q.db.QueryContext(ctx, getTopListQ, arg.Limit, arg.Offset) if err != nil { return nil, err } defer rows.Close() items := []GetTopListLocationsRow{} for rows.Next() { var i GetTopListLocationsRow if err := rows.Scan( &i.RowNumber, &i.ID, &i.Name, &i.Address, &i.RegionName, &i.GoogleMapsLink, &i.Thumbnail, &i.RegencyName, &i.CriticScore, &i.CriticCount, &i.UserScore, &i.UserCount, &i.CriticBayes, &i.UserBayes, &i.AvgBayes, ); err != nil { return nil, err } i.TotalCount = i.UserCount + i.CriticCount items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil }