【问题标题】:calculate average rating in sql server计算sql server中的平均评分
【发布时间】:2015-01-30 07:11:17
【问题描述】:

这是我的桌子:

我想获取那些包含 ServiceDescription "Plaster" 或 Skills "Plaster" 或 属于“石膏”类别,还想计算这些供应商的平均评分。

注意:如果没有任何供应商的审查,那么记录也应该来。

这是我的查询:

select * from UserDetails u
  ,VendorInCategory v
  ,CategoryMaster c
  ,Review rv
where v.CategoryId=c.Id 
and u.Id=r.UserId 
and u.Id=rv.VendorId  
and v.VendorId=u.Id 
and ((u.ServiceDescription like '%Plaster%' ) 
or (u.Skills like '%Plaster%') 
or (c.Name like '%Plaster%'))

上述查询中的问题是我没有得到没有审查的供应商。

但我也想要那个不包含评论但符合我的标准的供应商。

用户详情:

id     Servicedescription         Skills
1        Plaster                  plaster

2        construction             construvtion

3        plaster                  plaster

4        null                     null(not vendor)

5        null                     null(not vendor)

评论

id     CustomerId     Vendorid    rating

1       4                1          3

2       5                1          3

预期输出:

VendorId     ServiceDescription     Skills       averagerating

1              plaster              plaster           3

3              plaster              plaster           0

注意:最终输出应按平均评分的降序排列

【问题讨论】:

  • Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSI JOIN 语法-92 SQL 标准(20 多年前),不鼓励使用它
  • 您介意给我们样本数据和预期结果吗?
  • 我已经发布了示例输入和预期输出,请查看。
  • 可以请任何人向我询问我对此感到非常震惊

标签: sql sql-server sql-server-2008 select average


【解决方案1】:

很多用户都使用过AVERAGE函数来计算一系列数据的平均值。但是,当您有汇总数据而不是个人响应并且需要计算平均值时,您会怎么做? (例如,在 5 点评分量表上选择每个评分的人数,例如产品评分。)

如何计算加权平均值

假设您想获得每个产品的平均总体评分:

  • 对于等级 1,(9) 九人。
  • 对于等级 2,(13) 十三人。
  • 对于等级 3,(1) 一个人。

使用 AVERAGE 函数将得到 平均 7.7。当然,这没有任何意义。我们应该期望在标度范围内(1 到 5)的平均值。

为了正确计算每个问题的平均总体回答,我们需要:

  1. 将选择每个评级的个人数量乘以 对应的评分值 (1 – 5)
  2. 将这些计算的结果相加。
  3. 将该结果除以对该问题的回答总数。

例子:

    SELECT
    SUM(
    case 
        WHEN FLOOR(rating) = 1 THEN rating
        WHEN FLOOR(rating) = 2 THEN rating *2
        WHEN FLOOR(rating) = 3 THEN rating *3
        WHEN FLOOR(rating) = 4 THEN rating *4
        WHEN FLOOR(rating) = 5 THEN rating *5        
    end    
    ) / SUM(rating)
    FROM tableRatings

【讨论】:

    【解决方案2】:

    使用聚合函数AVG()

    试试这个:

    SELECT u.id, u.ServiceDescription, u.Skills, u.fullname, u.email, AVG(ISNULL(rv.rating, 0)) averagerating
    FROM UserDetails u 
    INNER JOIN VendorInCategory v ON v.VendorId=u.Id 
    INNER JOIN CategoryMaster c ON v.CategoryId=c.Id 
    LEFT JOIN Review rv ON u.Id=rv.VendorId  
    WHERE (u.ServiceDescription LIKE '%Plaster%' OR u.Skills LIKE '%Plaster%' OR 
           c.Name LIKE '%Plaster%')
    GROUP BY u.id, u.ServiceDescription, u.Skills, u.fullname, u.email
    ORDER BY averagerating DESC;
    

    编辑

    实现此的其他解决方案:

    SELECT u.id, u.ServiceDescription, u.Skills, u.fullname, u.email, 
           ISNULL(rv.averagerating, 0) averagerating
    FROM UserDetails u 
    INNER JOIN VendorInCategory v ON v.VendorId=u.Id 
    INNER JOIN CategoryMaster c ON v.CategoryId=c.Id 
    LEFT JOIN (SELECT rv.VendorId, AVG(rv.rating) averagerating FROM Review rv GROUP BY rv.VendorId) rv ON u.Id=rv.VendorId  
    WHERE (u.ServiceDescription LIKE '%Plaster%' OR u.Skills LIKE '%Plaster%' OR 
           c.Name LIKE '%Plaster%')
    ORDER BY ISNULL(rv.averagerating, 0) DESC;
    

    【讨论】:

    • 非常感谢您帮助我。非常感谢您,请继续提供帮助。因为像您这样的人,我总是喜欢在堆栈溢出时发布我的问题。
    • @mariapithia 然后,如果您没有在这些列上使用任何聚合函数,则必须在选择部分和按部分添加这些列
    • 如果我想包含更多详细信息,例如全名、电子邮件,那么我必须在我的 group by 子句中包含所有这些字段吗??
    • 您能否编辑您的查询并仅包含该字段,因为当我包含全名时,它会给我错误
    • 但你认为这不合适,因为我想在我的选择子句中包含超过 10 列
    【解决方案3】:

    在这里,试试这个:

    样本数据

    create table UserDetails(
        Id int,
        ServiceDescription varchar(20),
        Skills varchar(20)
    )
    create table Review(
        Id int,
        CustomerId int,
        VendorId int,
        Rating int
    )
    
    insert into UserDetails values(1, 'Plaster', 'plaster'),(2, 'construction', 'construction'),(3, 'plaster', 'plaster');
    insert into Review values(1, 4, 1, 3),(2, 5, 1, 3);
    

    解决方案

    select
        u.Id as VendorId,
        u.ServiceDescription,
        u.Skills,
        isnull(sum(r.rating)/count(r.rating), 0) as AverageRating
    from UserDetails u
    left join Review r
        on r.VendorId = u.id
    where
        u.ServiceDescription like '%plaster%'
        or u.Skills like '%plaster%'
    group by 
        u.Id,
        u.ServiceDescription,
        u.Skills
    order by AverageRating desc
    

    【讨论】:

    • 您可以将sum(s.rating)/count(r.rating) 替换为avg(r.rating)
    • 非常感谢您帮助我。非常感谢您,请继续提供帮助。因为像您这样的人,我总是喜欢在堆栈溢出时发布我的问题。
    • 没问题。很高兴我能帮上忙。
    • 但如果我想包含所有用户详细信息,如全名、电子邮件等...?
    • 如果我想包含更多详细信息,例如全名、电子邮件,那么我必须在我的 group by 子句中包含所有这些字段吗??
    猜你喜欢
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 2018-01-04
    • 2017-10-11
    • 2017-12-03
    相关资源
    最近更新 更多