使用select时,子查询在mysql中返回多行

时间:2015-05-23 03:09:18

标签: php mysql

我有两个表,用户和主题。

表用户

CREATE TABLE IF NOT EXISTS `user` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `usertype` int(11) DEFAULT '0',
  `useraccesskey` varchar(80) DEFAULT NULL,
  `userphone` varchar(80) DEFAULT NULL,
  `userpassword` varchar(80) DEFAULT NULL,
  `usernickname` varchar(80) DEFAULT NULL,
  `userphoto` varchar(80) NOT NULL,
  PRIMARY KEY (`userid`)
 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

表主题

CREATE TABLE IF NOT EXISTS `topic` (
 `topicid` int(11) NOT NULL AUTO_INCREMENT,
 `btid` int(11) NOT NULL,
 `topictitle` varchar(80) NOT NULL,
 `topiccontent` text NOT NULL,
 `topicisdel` int(11) NOT NULL,
 `topicdate` varchar(80) NOT NULL,
 `authorid` int(11) NOT NULL,
 `useraccesskey` varchar(80) NOT NULL DEFAULT '0',
 `topicistop` int(11) NOT NULL DEFAULT '0',
 `topicishot` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`topicid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1605 ;

我使用此sql查询列出所有信息

select b.*, (select userphoto from user u where u.useraccesskey = b.useraccesskey) as headpic, (select usernickname from user u where u.useraccesskey = b.useraccesskey) as nickname from topic b where b.topicisdel = 0 and b.btid = 3 order by b.topicistop desc, b.topicishot desc, b.topicid desc"

但结果告诉我Subquery returns more than 1 row,但我检查了所有信息,没有,我不知道为什么,请帮助我,谢谢。

2 个答案:

答案 0 :(得分:0)

SELECT列表中的子查询返回了多行。 MySQL只能在该上下文中处理一个标量值,因此我们必须保证子查询不会返回两行或更多行。

"快速修复"避免错误是在每个子查询上添加一个LIMIT 1,以便它最多返回 一行。

我还建议ORDER BY使结果更具确定性。我们不知道user表中包含哪些其他列,所以我只引用了SELECT返回的列。

例如:

SELECT b.*
     , ( SELECT u.userphoto 
           FROM user u
          WHERE u.useraccesskey = b.useraccesskey
          ORDER BY 1 LIMIT 1                -- return at most one row
       ) AS headpic
     , ( SELECT u.usernickname 
           FROM user u 
          WHERE u.useraccesskey = b.useraccesskey
          ORDER BY 1 LIMIT 1                -- return at most one row
       ) AS nickname
  FROM topic b 
 WHERE b.topicisdel = 0 
   AND b.btid = 3
 ORDER
    BY b.topicistop DESC
     , b.topicishot DESC
     , b.topicid DESC

我不认为这是最好的"解决问题的方法。我试图解释导致问题的原因,以及解决问题的可能方法。

要查看返回多行的位置,我们可以将另一个子查询添加到SELECT列表...

     , ( SELECT u.userphoto 
           FROM user u
          WHERE u.useraccesskey = b.useraccesskey
          ORDER BY 1 LIMIT 1,1              -- return value from 2nd row if it exists
       ) AS headpic_2

如果userphoto可以为NULL,那可能不会给我们提供太多指示,因为我们无法区分行返回的NULL或返回的NULL,因为行没有& #39; t存在。

我们可以在SELECT列表中获得用户与另一个子查询匹配的行数:

     , ( SELECT COUNT(*)
           FROM user u
          WHERE u.useraccesskey = b.useraccesskey
       ) AS count_matching_rows_in_user

请注意useraccesskey列不保证在user中是唯一的。如果没有该保证,我们必须预期可能存在重复值,即user中有useraccesskey的{​​{1}}具有相同值的多行。

答案 1 :(得分:0)

所以看起来你更喜欢这样的事情 - 虽然没有数据集和结果集,但总是很难确定......

select b.*
     , u.userphoto headpic
     , u.usernickname nickname
  from topic b
  join user u
    on u.useraccesskey = b.useraccesskey 
 where b.topicisdel = 0 
   and b.btid = 3 
 order 
    by b.topicistop desc
     , b.topicishot desc
     , b.topicid desc