添加country_id约束后记录数增加及revenue_usd=0条件失效问题
SQL问题解答
问题1:添加country_id约束后查询返回记录数反而增加的原因
第一个查询返回30条记录:
SELECT app_id, sum(installs) FROM application.app JOIN sales.app_total ON sales.app_total.app_id = application.app.id WHERE sales.app_total.date BETWEEN '2023-05-01' AND '2023-05-07' AND application.app.app_market_id = 4 AND country_id = 100 GROUP BY app_id HAVING CAST((sum(sales.app_total.revenue_usd) * 0.2) / 1 AS FLOAT) >= 0 AND CAST((sum(sales.app_total.revenue_usd) * 0.2) / 1 AS FLOAT) <= 0
第二个查询返回8条记录:
SELECT sum(installs) FROM application.app JOIN sales.app_total ON sales.app_total.app_id = application.app.id WHERE sales.app_total.date BETWEEN '2023-05-01' AND '2023-05-07' AND application.app.app_market_id = 4 GROUP BY app_id HAVING CAST ((sum(sales.app_total.revenue_usd) * 0.2) / 1 AS FLOAT) >= 0 AND CAST((sum(sales.app_total.revenue_usd) * 0.2) / 1 AS FLOAT) <= 0
原因分析
核心差异是country_id过滤对分组后聚合结果的影响:
country_id属于sales.app_total表,第一个查询仅筛选该国家的记录,第二个查询包含所有国家的记录。HAVING条件本质是要求分组后sum(revenue_usd)*0.2的结果等于0:- 第二个查询中,部分
app_id对应多条不同国家的sales.app_total记录,这些记录的revenue_usd总和可能不为0,因此被HAVING过滤,最终仅剩下8条符合条件的分组。 - 第一个查询仅保留
country_id=100的记录,部分app_id在该国家的revenue_usd总和恰好为0,符合HAVING条件,因此保留的分组数(30条)远多于第二个查询。
- 第二个查询中,部分
问题2:revenue_usd = 0条件未生效,仍累加有收入记录的原因
问题查询语句:
SELECT country_id, sum(installs), sum(revenue_usd) as rev FROM sales.app_total JOIN application.app ON application.app.id = sales.app_total.app_id WHERE date = '2023-05-01' AND application.app.app_market_id IN (4) AND revenue_usd = 0 GROUP BY country_id
原因分析
最可能的原因是未明确指定revenue_usd所属的表:
revenue_usd是sales.app_total表的字段,但查询中WHERE条件的revenue_usd = 0未添加表前缀。若application.app表存在同名字段,数据库会优先匹配该表的字段;如果application.app.revenue_usd取值全为0,这个条件不会过滤任何sales.app_total的记录,导致有收入的记录依然被加入聚合。
另外两种可能:
- 浮点精度问题:若
revenue_usd是浮点类型,部分记录的实际值是接近0的极小非0数(如0.0000001),直接用=判断无法匹配,需改用范围判断(如revenue_usd BETWEEN -0.0001 AND 0.0001)。 - 混淆
WHERE与HAVING的作用:如果需求是筛选分组后sum(revenue_usd)=0的国家,而非单个记录revenue_usd=0,则应将条件放在HAVING中,而非WHERE。
解决建议
优先给字段添加明确的表前缀,避免歧义:
SELECT country_id, sum(installs), sum(sales.app_total.revenue_usd) as rev FROM sales.app_total JOIN application.app ON application.app.id = sales.app_total.app_id WHERE sales.app_total.date = '2023-05-01' AND application.app.app_market_id IN (4) AND sales.app_total.revenue_usd = 0 GROUP BY country_id
内容的提问来源于stack exchange,提问作者danilchik22
相关产品推荐
相关产品推荐

