使用两次Inner Join仅返回5行数据,h.Hours计数异常求助
问题分析与修正方案
核心问题1:结果行数远少于预期
两次Inner Join会过滤掉没有关联review记录或者没有关联hours记录的商家,只有同时满足两个关联条件的商家才会出现在结果集中,这就是返回行数远低于预期的原因。
核心问题2:营业天数统计值异常
Inner Join review与Inner Join Hours会产生笛卡尔积:比如某商家有10条review、7条hours记录,关联后会生成70条重复数据,Count(h.Hours)实际统计的是关联后的总条数,而非真实的营业天数。
修正后的SQL示例
方案1:保留所有有review的商家(允许无hours数据),并正确统计营业天数
Select b.Name ,Sum(b.review_count) As TotalReviews ,Strftime('%Y', r.date) As Year ,Count(r.text) As WrittenReviews ,Count(DISTINCT h.day) As OpenDays -- 假设hours表有day字段记录星期,用DISTINCT去重统计真实天数 ,Case When b.Is_Open = 1 Then 'Open' Else 'Close' End IsItOpen From business b Inner Join review r On r.business_id = b.id Left Join Hours h On b.id = h.business_id -- 改为Left Join,保留有review但无hours的商家 Group By b.name, Strftime('%Y', r.date) -- 按商家名+年份分组,符合SQL标准 Order By TotalReviews DESC
方案2:先聚合hours表再关联(彻底避免笛卡尔积)
如果hours表每条记录对应一天,先提前统计每个商家的营业天数,再与其他表关联:
With BusinessHours As ( Select business_id, Count(*) As OpenDays From Hours Group By business_id ) Select b.Name ,Sum(b.review_count) As TotalReviews ,Strftime('%Y', r.date) As Year ,Count(r.text) As WrittenReviews ,Coalesce(bh.OpenDays, 0) As OpenDays -- 无hours数据时显示0 ,Case When b.Is_Open = 1 Then 'Open' Else 'Close' End IsItOpen From business b Inner Join review r On r.business_id = b.id Left Join BusinessHours bh On b.id = bh.business_id Group By b.name, Strftime('%Y', r.date) Order By TotalReviews DESC
额外注意点
- 原SQL中
Group By b.name但Select包含Strftime('%Y', r.date),这不符合SQL标准(部分数据库可能允许但结果不可控)。同一个商家可能有不同年份的review,必须将Year加入Group By,或对Year做聚合(比如Max(Strftime('%Y', r.date)))。 - 如果需要保留所有商家(不管有没有review),把
Inner Join review改成Left Join review即可,聚合函数会自动处理NULL值(比如Count(r.text)会忽略无review的情况,显示为0)。
内容的提问来源于stack exchange,提问作者Alfredo
相关产品推荐
相关产品推荐

