ошибка: # 1242 - подзапрос возвращает более 1 строки - PullRequest
2 голосов
/ 23 октября 2011

Я получил ошибку: # 1242 - Подзапрос возвращает более 1 строки, когда я запускаю этот sql.

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 ]

4 голосов
/ 23 октября 2011

Проблема в том, что ваши подвыборы возвращают более одного значения - 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
2 голосов
/ 23 октября 2011

Это потому, что ваши подзапросы (биты 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, вам на самом деле не нужно использовать подзапросы, если вы этого не хотите.

1 голос
/ 23 октября 2011

Ваши подзапросы возвращают более 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 + pivoting (в основном в учебных целях, это гораздо более длинный запрос):

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
0 голосов
/ 23 октября 2011
SELECT COUNT() 
          FROM   bed 
          WHERE  respatient_id > 0 
          GROUP  BY cc_name

Вам нужно удалить группировку в подзапросе, поэтому возможно что-то вроде

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
...