求助:SQL查询按pr_codenum返回多行,需实现一行对应一个pr_codenum
嗨,我来帮你梳理下这个问题的解决思路~
你遇到的核心问题是:想用GROUP BY pr_codenum实现每个pr_codenum对应一行结果,但没生效。大概率是因为你没有对P01、P02这类设施列做聚合处理,或者GROUP BY的语法不符合数据库的严格模式要求。
一、先排查GROUP BY的语法问题
很多数据库(比如PostgreSQL、MySQL开启严格模式时)要求:SELECT子句里的非聚合列必须全部出现在GROUP BY中。如果你的原查询是类似下面这样:
SELECT pr_codenum, P01, P02, ..., P20 FROM your_table GROUP BY pr_codenum;
这会导致两种情况:要么直接报错,要么数据库随机返回每组中的某一行(看起来还是多行,其实是每组一行但你误以为是重复)。
二、针对设施列做聚合处理
因为每个pr_codenum对应多行数据,每行的P01/P02等值可能不同(true/false/空白),你需要明确:对于同一个pr_codenum,这些设施列最终要展示什么结果?
常见的需求和对应处理方式:
只要该pr_codenum下有一个true,就显示true,否则显示false
利用布尔值的特性(通常true=1,false=0),用MAX()聚合函数取最大值:SELECT pr_codenum, -- 先处理空白值:把空白转成false,再取MAX MAX(CASE WHEN P01 = '' THEN FALSE ELSE P01 END) AS P01, MAX(CASE WHEN P02 = '' THEN FALSE ELSE P02 END) AS P02, -- 重复上述逻辑到P20 MAX(CASE WHEN P20 = '' THEN FALSE ELSE P20 END) AS P20 FROM your_table GROUP BY pr_codenum;只要该pr_codenum下有一个false,就显示false,否则显示true
换成MIN()聚合函数即可:SELECT pr_codenum, MIN(CASE WHEN P01 = '' THEN FALSE ELSE P01 END) AS P01, MIN(CASE WHEN P02 = '' THEN FALSE ELSE P02 END) AS P02, -- ... 到P20 FROM your_table GROUP BY pr_codenum;统计每个设施列的状态分布
如果需要更详细的信息(比如true的数量、false的数量),可以用COUNT()配合CASE:SELECT pr_codenum, COUNT(CASE WHEN P01 = TRUE THEN 1 END) AS P01_true_count, COUNT(CASE WHEN P01 = FALSE THEN 1 END) AS P01_false_count, -- ... 其他设施列同理 FROM your_table GROUP BY pr_codenum;
三、额外提醒:处理空白值
你提到设施列可能有空白,这里的空白可能是空字符串''或者NULL,上面的例子用CASE WHEN P01 = '' THEN FALSE处理了空字符串,如果是NULL,可以换成COALESCE(P01, FALSE)来统一转成false:
MAX(COALESCE(P01, FALSE)) AS P01
按照这个思路调整你的查询,应该就能实现每个pr_codenum对应一行结果啦~
内容的提问来源于stack exchange,提问作者user9388067

