错误:#1242 - 子查询返回超过1行

时间:2011-10-23 16:00:05

标签: mysql sql mysql-error-1242

我收到错误:#1242 - 运行此sql时,子查询返回的行数超过1行。

CREATE VIEW test 
AS 
  SELECT cc_name, 
         COUNT() AS total, 
         (SELECT COUNT(*) 
            FROM bed 
           WHERE respatient_id > 0 
        GROUP BY cc_name) AS occupied_beds, 
         (SELECT COUNT(*) 
            FROM bed 
           WHERE respatient_id IS NULL 
        GROUP BY cc_name) AS free_beds 
    FROM bed 
GROUP BY cc_name; 

4 个答案:

答案 0 :(得分:4)

问题是您的子选择返回多个值 - IE:

SELECT ...
       (SELECT COUNT(*) 
          FROM bed 
         WHERE respatient_id IS NULL 
      GROUP BY cc_name) AS free_beds,
       ...

...将为每个cc_name返回一行,但SQL不支持压缩子选择的结果集 - 因此错误。

不需要子选择,可以使用以下方法在表上进行单次传递:

  SELECT b.cc_name, 
         COUNT(*) AS total, 
         SUM(CASE 
               WHEN b.respatient_id > 0 THEN 1 
               ELSE 0 
             END) AS occupied_beds, 
         SUM(CASE 
               WHEN b.respatient_id IS NULL THEN 1 
               ELSE 0 
             END) AS free_beds 
    FROM bed b
GROUP BY b.cc_name

答案 1 :(得分:2)

这是因为您的子查询(括号内的SELECT位)为每个外行返回多行。问题出在GROUP BY;如果你想为此使用子查询,那么你需要与外部查询相关联,方法是指定它们引用与外部查询相同的cc_name

CREATE VIEW test 
AS 
  SELECT cc_name, 
         COUNT()             AS total, 
         (SELECT COUNT() 
          FROM   bed 
          WHERE  cc_name = bed_outer.cc_name
          AND    respatient_id > 0) AS occupied_beds, 
         (SELECT COUNT(*) 
          FROM   bed 
          WHERE  cc_name = bed_outer.cc_name
          WHERE  respatient_id IS NULL) AS free_beds 
  FROM   bed AS bed_outer
  GROUP  BY cc_name;

(有关相关子查询的信息,请参阅http://en.wikipedia.org/wiki/Correlated_subquery。)

但是,正如OMG Ponies和a1ex07所说,如果你不愿意,你实际上并不需要使用子查询。

答案 2 :(得分:1)

您的子查询返回超过1行。我想你需要这样的东西:

 SELECT COUNT(*) AS total, 
 COUNT(CASE WHEN respatient_id > 0 THEN 1 END) AS occupied_beds,
 COUNT(CASE WHEN respatient_id IS NULL THEN 1 END) AS free_beds          
 FROM   bed 
 GROUP  BY cc_name

您还可以尝试使用WITH ROLLUP +旋转(主要用于学习目的,这是一个更长的查询):

SELECT cc_name, 
MAX(CASE 
 WHEN num_1 = 1 THEN tot_num END) AS free_beds,

MAX(CASE 
 WHEN num_1 = 2 THEN tot_num END) AS occupied_beds,

MAX(CASE 
 WHEN num_1 = IS NULL THEN tot_num END) AS total

FROM
(SELECT cc_name, CASE 
WHEN respatient_id > 0 THEN 1
WHEN respatient_id IS NULL THEN 2
ELSE 3 END as num_1,
COUNT(*) as tot_num
FROM  bed
WHERE 
CASE 
WHEN respatient_id > 0 THEN 1
WHEN respatient_id IS NULL THEN 2
ELSE 3 END != 3
GROUP BY cc_name,
num_1 WITH ROLLUP)A
GROUP BY cc_name

答案 3 :(得分:0)

SELECT COUNT() 
          FROM   bed 
          WHERE  respatient_id > 0 
          GROUP  BY cc_name

您需要在子查询中删除group-by,因此可能类似

SELECT COUNT(*) 
          FROM   bed 
          WHERE  respatient_id > 0 

或可能 - 取决于您的应用逻辑是什么......

SELECT COUNT(*) from (
          select count(*),cc_name FROM   bed 
          WHERE  respatient_id > 0 
          GROUP  BY cc_name) filterview