在条件中使用COALESCE与别名:ad_params表交叉表查询异常
嘿,咱们一步步来解决这个问题。看起来你在基于ad_params表做交叉表的时候遇到了两个小问题:一是CASE语句里的ad_params.value='cordova'条件没达到预期效果,二是需要过滤掉model字段为空的行。我来帮你理清楚。
先分析原语句的逻辑问题
你原来写的语句:
coalesce(max(CASE when ad_params.name='model' and ad_params.value='cordova'then ad_params.value end ),NULL)
这里的CASE逻辑是仅当某一行同时满足name='model'和value='cordova'时,才返回该值,其他所有情况(包括name='model'但value不是cordova的行)都返回NULL。然后用MAX聚合后,只有当分组内存在model=cordova的行时,model字段才会显示cordova,否则就是NULL。但你可能想要的是:先提取所有model的值,再筛选出值为cordova的行,或者直接只保留model=cordova的记录。
解决方案1:聚合后过滤(保留其他交叉字段时用)
如果你的交叉表还需要展示其他参数(比如platform、version等),可以先完成所有字段的交叉聚合,再用HAVING子句过滤掉model不为cordova的行(自动排除NULL的情况):
SELECT ad_id, -- 替换成你的实际分组字段,比如广告ID、投放时间等 MAX(CASE WHEN ad_params.name = 'model' THEN ad_params.value END) AS model, MAX(CASE WHEN ad_params.name = 'platform' THEN ad_params.value END) AS platform, -- 示例其他交叉字段 MAX(CASE WHEN ad_params.name = 'version' THEN ad_params.value END) AS version -- 示例其他交叉字段 FROM ad_params GROUP BY ad_id -- 只保留model为cordova的行,NULL会自动被排除(因为NULL不等于任何值) HAVING MAX(CASE WHEN ad_params.name = 'model' THEN ad_params.value END) = 'cordova'
这里不需要COALESCE,因为MAX在没有匹配行时会返回NULL,而HAVING里的判断会直接排除这些NULL行。
解决方案2:先过滤再聚合(性能更优)
如果你的需求只是获取model=cordova的交叉表结果,优先用这种写法——先在WHERE里过滤掉不符合条件的行,再聚合,能减少数据处理量,速度更快:
SELECT ad_id, MAX(CASE WHEN ad_params.name = 'model' THEN ad_params.value END) AS model, MAX(CASE WHEN ad_params.name = 'platform' THEN ad_params.value END) AS platform FROM ad_params -- 先过滤出model为cordova的行,同时保留其他参数的行(如果不需要其他参数,可以简化WHERE条件) WHERE (ad_params.name = 'model' AND ad_params.value = 'cordova') OR ad_params.name != 'model' GROUP BY ad_id
如果不需要其他交叉字段,还可以更简洁:
SELECT ad_id, MAX(ad_params.value) AS model FROM ad_params WHERE ad_params.name = 'model' AND ad_params.value = 'cordova' GROUP BY ad_id
为什么原条件“没生效”?
其实原语句的逻辑本身是能返回cordova或NULL的,但如果你的分组内存在name='model'但value不是cordova的行,这些行在CASE里会被转为NULL,MAX后还是NULL——这时候你需要的就是过滤掉这些NULL行,而上面的两种方案都能实现这个需求。
内容的提问来源于stack exchange,提问作者Medone

