PostgreSQL子查询报错:subquery must return only one column 求助
解决PostgreSQL报错:ERROR: subquery must return only one column
问题描述
编写报表查询SQL时触发如下错误:
ERROR: subquery must return only one column - postgresql
原SQL代码如下:
select public.produtofornecedor.id_fornecedor, public.fornecedor.nomefantasia, public.produto.id as item, public.produto.descricaocompleta, public.produtoautomacao.codigobarras, public.produtocomplemento.descontinuado, (select descricao as status from situacaocadastro where id=1 and (select id as numero_loja,descricao from loja where id <> 2)) from public.produto join public.produtofornecedor on public.produto.id = public.produtofornecedor.id_produto join public.produtoautomacao on public.produto.id = public.produtoautomacao.id_produto join public.fornecedor on public.fornecedor.id = public.produtofornecedor.id_fornecedor join public.produtocomplemento on public.produtocomplemento.id_produto = public.produtoautomacao.id_produto where public.produtocomplemento.descontinuado = false and public.produtofornecedor.id_fornecedor = 611 order by public.produto.id;
错误原因
报错的核心在于子查询返回了多列:
- 外层子查询
(select descricao as status from situacaocadastro ...)的条件中,嵌套了(select id as numero_loja,descricao from loja where id <> 2),这个嵌套子查询同时返回了id和descricao两列,但作为WHERE条件中的子查询,必须仅返回单一列。 - 此外,若
loja表中存在多条id <> 2的记录,该嵌套子查询会返回多行,同样会触发PostgreSQL的条件子查询不能返回多行的限制。
修正方案
根据业务逻辑调整子查询写法,以下是两种常见解决方案:
方案1:用EXISTS判断存在性(适合仅需判断是否有符合条件的门店)
select public.produtofornecedor.id_fornecedor, public.fornecedor.nomefantasia, public.produto.id as item, public.produto.descricaocompleta, public.produtoautomacao.codigobarras, public.produtocomplemento.descontinuado, (select descricao as status from situacaocadastro where id=1 and EXISTS (select 1 from loja where id <> 2)) as status from public.produto join public.produtofornecedor on public.produto.id = public.produtofornecedor.id_produto join public.produtoautomacao on public.produto.id = public.produtoautomacao.id_produto join public.fornecedor on public.fornecedor.id = public.produtofornecedor.id_fornecedor join public.produtocomplemento on public.produtocomplemento.id_produto = public.produtoautomacao.id_produto where public.produtocomplemento.descontinuado = false and public.produtofornecedor.id_fornecedor = 611 order by public.produto.id;
方案2:直接JOIN关联表(如果需要获取loja表的字段)
若需同时获取门店相关信息,建议将子查询改为JOIN,避免嵌套子查询的问题:
select public.produtofornecedor.id_fornecedor, public.fornecedor.nomefantasia, public.produto.id as item, public.produto.descricaocompleta, public.produtoautomacao.codigobarras, public.produtocomplemento.descontinuado, sc.descricao as status, l.id as numero_loja, l.descricao as loja_descricao from public.produto join public.produtofornecedor on public.produto.id = public.produtofornecedor.id_produto join public.produtoautomacao on public.produto.id = public.produtoautomacao.id_produto join public.fornecedor on public.fornecedor.id = public.produtofornecedor.id_fornecedor join public.produtocomplemento on public.produtocomplemento.id_produto = public.produtoautomacao.id_produto -- 关联situacaocadastro和loja表 cross join public.situacaocadastro sc cross join public.loja l where sc.id = 1 and l.id <> 2 and public.produtocomplemento.descontinuado = false and public.produtofornecedor.id_fornecedor = 611 order by public.produto.id;
注:如果situacaocadastro和loja是一对一关联,可根据实际业务调整JOIN类型(比如INNER JOIN)。
内容的提问来源于stack exchange,提问作者Luiz
相关产品推荐
相关产品推荐

