Group BY 子查询返回多于 1 行

Posted

技术标签:

【中文标题】Group BY 子查询返回多于 1 行【英文标题】:Group BY Subquery returns more than 1 row 【发布时间】:2013-01-26 14:09:41 【问题描述】:

第一个我是 mysql 菜鸟 :D 我试过搜索,但没有任何帮助。 我正在尝试使用此查询更新我的数据库。

UPDATE client SET cntr_limit=(SELECT fulltraffic from 
(SELECT
    client.id,
    (SUM(ipacct.byteso)+SUM(ipacct.bytesi)) as fulltraffic
        FROM client 
            LEFT JOIN ips ON client.id = ips.cid
            LEFT JOIN ipacct ON ips.ip = ipacct.target
            WHERE ipacct.tag = 1
        GROUP BY client.id
     ) as x
) +322122547200 ;

我得到子查询返回超过 1 行。 我知道子查询不能超过一行,但我需要使用 GROUP BY。如果我删除 GROUP BY 查询有效,但每个客户端都获得从所有 ips 计算的流量, 而不是为每个 id 计算不同的流量。

如果我使用。

 SELECT
    client.id,
    (SUM(ipacct.byteso)+SUM(ipacct.bytesi)) as fulltraffic
        FROM client 
            LEFT JOIN ips ON client.id = ips.cid
            LEFT JOIN ipacct ON ips.ip = ipacct.target
            WHERE ipacct.tag = 1
        GROUP BY client.id;

我得到了

id  fulltraffic
1   5100993724986
3   410550845834
4   790726628007
5   204212941099
6   440290245087
8   587044969960

如果我删除 GROUP BY 我正在获取

id  fulltraffic
1   487196626849368

提前致谢。

【问题讨论】:

你能显示表模式吗?以及一些示例数据.. 【参考方案1】:

使用IN 而不是=

UPDATE client SET cntr_limit IN (SELECT....

并删除最后一个别名+322122547200 ;

但更好的方法是在UPDATE 语句中加入表格,

UPDATE  client a
        INNER JOIN
        (
            SELECT  client.id,
                    (SUM(ipacct.byteso)+SUM(ipacct.bytesi)) as fulltraffic
            FROM    client 
                    LEFT JOIN ips 
                        ON client.id = ips.cid
                    LEFT JOIN ipacct ON ips.ip = ipacct.target
            WHERE   ipacct.tag = 1
            GROUP   BY client.id
        ) b ON a.id = b.id
SET     a.cntr_limit = b.fulltraffic

【讨论】:

我还有一个问题,+322122547200 是什么? 它将 +300 GB 的流量添加到已计算的流量中。 所以UPDATE 语句应该是SET a.cntr_limit = b.fulltraffic + 322122547200【参考方案2】:

如果我删除 GROUP BY 查询有效,但每个客户端都获得从所有 ips 计算的流量,而不是为每个 id 计算不同的流量。

是的,这正是您想要的。如果您只想要一行,那么您缺少的是指定 client.id 的 where 子句

如果您想要做的只是将cntr_limit 更新为所有客户端的完整流量 + 322122547200,那么您的查询很好,并且会立即更新所有客户端各自的总数。

如果您一次处理一个客户端,则需要按 client.id 过滤

【讨论】:

【参考方案3】:

如何使用相关子查询进行连接更新:

SQLFIDDLE DEMO

UPDATE client c
INNER JOIN
(SELECT a.id as id,
 (SUM(ipact.byteso) + SUM(ipact.bytesi)) as ft
 FROM client a
 LEFT JOIN ips ON a.id = ips.cid
 LEFT JOIN ipact ON ips.id = ipact.ipp
            WHERE ipact.tag = 1
        GROUP BY a.id
     ) x
on c.id = x.id
SET c.climit = x.ft
;

【讨论】:

我相信您正在将322122547200 值添加到您设置到cntr_limit.. 的每个新值中:)

以上是关于Group BY 子查询返回多于 1 行的主要内容,如果未能解决你的问题,请参考以下文章

SQL 不能使用从 group by 中的子查询返回的列

多表查询

得到以下错误 ORA-01427: 单行子查询返回多于一行 01427. 00000 - “单行子查询返回多于一行”

SQL查询时错误:子查询返回的值多于一个

查询返回:ORA-01427 单行子查询返回多于一行

mysql n:m 关系删除查询 1242 子查询返回多于 1 行