错误:子查询必须只返回一列

时间:2013-10-29 03:28:05

标签: sql postgresql join left-join cross-join

当我尝试运行以下查询时,收到错误subquery must return only one column

SELECT mat.mat as mat1, sum(stx.total ) as sumtotal1,
  (
    SELECT mat.mat  as mat, sum(stx.total)  as sumtotal
    FROM stx 
      LEFT JOIN mat ON stx.matid = mat.matid
      LEFT JOIN sale ON stx.saleid = sale.id
    WHERE stx.date BETWEEN '2013-05-01' AND '2013-08-31' 
      AND sale.userid LIKE 'A%'
    GROUP BY mat.mat
) AS MyField
FROM stx 
  LEFT JOIN mat ON stx.matid = mat.matid
  LEFT JOIN sale ON stx.saleid = sale.id
WHERE stx.date BETWEEN '2013-05-01' AND '2013-08-31'
  AND sale.userid LIKE 'B%'
GROUP BY mat.mat

导致此错误的原因是什么?

2 个答案:

答案 0 :(得分:11)

放置一个子查询,返回FROM列表中的多个列并从中进行选择。

相关的子查询首先是一个坏主意。但是,您的查询甚至没有关联,但无关(没有链接到外部查询)并且似乎返回多行。这导致(可能非常昂贵和荒谬的)交叉连接产生笛卡尔积,可能不是你的(秘密)意图。

看起来你真的想要:

SELECT m1.mat AS mat1, m1.sumtotal AS sumtotal1
      ,m2.mat AS mat2, m2.sumtotal AS sumtotal2
FROM (
   SELECT mat.mat, sum(stx.total) AS sumtotal
   FROM   stx 
   LEFT   JOIN mat ON mat.matid = stx.matid
   LEFT   JOIN sale ON stx.saleid = sale.id
   WHERE  stx.date BETWEEN '2013-05-01' AND '2013-08-31'
   AND    sale.userid LIKE 'A%'
   GROUP  BY mat.mat
   ) m1
JOIN  (
   SELECT mat.mat, sum(stx.total) AS sumtotal
   FROM   stx 
   LEFT   JOIN mat ON mat.matid = stx.matid
   LEFT   JOIN sale ON sale.id = stx.saleid
   WHERE  stx.date BETWEEN '2013-05-01' AND '2013-08-31' 
   AND    sale.userid LIKE 'b%'
   GROUP  BY mat.mat
   ) m2 USING (mat);

两个LEFT JOIN也毫无意义。 sale上的那个被WHERE条件强制为INNER JOIN。垫子上的那个似乎没有意义,因为你GROUP BY mat.mat - 除非你对mat IS NULL感兴趣? (我对此表示怀疑。)

案件可以进一步简化为:

SELECT m.mat
      ,sum(CASE WHEN s.userid LIKE 'A%' THEN x.total END) AS total_a
      ,sum(CASE WHEN s.userid LIKE 'B%' THEN x.total END) AS total_b
FROM   sale s 
JOIN   stx  x ON x.saleid = s.id
JOIN   mat  m ON m.matid = x.matid
WHERE (s.userid LIKE 'A%' OR s.userid LIKE 'B%')
AND    x.date BETWEEN '2013-05-01' AND '2013-08-31'
GROUP  BY 1;

WHERE条件可能会进一步简化,具体取决于您的秘密数据类型和索引。关于this related answer on dba.SE中的案例的大量信息。

答案 1 :(得分:1)

而不是子查询select语句

SELECT mat.mat  as mat, sum(stx.total)  as sumtotal

试试这句话

SELECT sum(stx.total)  as sumtotal