Redshift:使用SELECT *时子查询无匹配如何默认字段为0
问题解答
首先明确:可以通过修改子查询的逻辑,让主查询用SELECT *就能得到默认0的结果,不需要在主查询里逐个字段加NVL/COALESCE。
可行方案:子查询基于WIDGETS左连接聚合
你的问题根源是:原中子查询仅从WIDGET_ISSUES聚合,没有对应widget_id的行根本不会输出,导致主查询左连接后这些字段为NULL。如果让子查询先以WIDGETS为基础左连接WIDGET_ISSUES,再聚合,就能保证每个widget_id都有一行结果,聚合值自然为0而非NULL:
SELECT * FROM WIDGETS LEFT JOIN ( -- 子查询先关联WIDGETS,确保每个widget_id都被包含 SELECT w.widget_id, COUNT(wi.widget_id) AS total, -- 用COUNT(wi.widget_id)避免统计空行 SUM(CASE WHEN wi.status='closed' THEN 1 ELSE 0 END) AS open, SUM(CASE WHEN wi.status='open' THEN 1 ELSE 0 END) AS closed FROM WIDGETS w LEFT JOIN WIDGET_ISSUES wi ON w.widget_id = wi.widget_id GROUP BY w.widget_id ) AS ISSUES ON WIDGETS.widget_id = ISSUES.widget_id
为什么原方案不行?
原中子查询仅从WIDGET_ISSUES取数,没有对应问题的widget_id不会生成任何行。主查询左连接时,这部分WIDGETS的ISSUES.*字段会被填充为NULL——这种NULL是左连接本身的行为,和子查询里的聚合函数无关,所以在子查询内部加NVL/COALESCE根本起不到作用(因为子查询根本没输出这些行)。
替代方案(如果不能修改子查询的数据源)
如果因为权限或其他原因,子查询不能基于WIDGETS构建,那确实只能在主查询里处理NULL。但可以用一些简化写法减少重复工作:
- 用CTE或视图封装主查询的字段处理逻辑,后续直接查询视图即可
- 示例视图创建语句:
CREATE VIEW WIDGETS_WITH_ISSUES AS SELECT w.*, NVL(i.total, 0) AS total, NVL(i.open, 0) AS open, NVL(i.closed, 0) AS closed FROM WIDGETS w LEFT JOIN (原中子查询内容) i ON w.widget_id = i.widget_id
之后直接SELECT * FROM WIDGETS_WITH_ISSUES即可。
内容的提问来源于stack exchange,提问作者Doug
相关产品推荐
相关产品推荐

