通过子查询得到没有组的总和

时间:2014-06-04 11:45:01

标签: mysql group-by sum subquery

我有两张桌子,例如:

BALANCE             VS
╔══════╦══════╗     ╔══════╦═══════╗
║ V_ID ║ BAL  ║     ║ V_ID ║ NAME  ║
╠══════╬══════╣     ╠══════╬═══════╣
║    1 ║ 1000 ║     ║    1 ║ Carl  ║
║    1 ║  500 ║     ║    2 ║ Peter ║
║    1 ║ -200 ║     ╚══════╩═══════╝
║    2 ║  350 ║     
║    2 ║ 1000 ║     
╚══════╩══════╝

现在我做了一个类似的查询:

select 
    NAME,sum(BAL)
from VS,BALANCE
where VS.V_ID = BALANCE.V_ID
group by NAME

结果是:

╔═══════╦══════╗
║ NAME  ║ BAL  ║
╠═══════╬══════╣
║ Carl  ║ 1300 ║
║ Peter ║ 1350 ║
╚═══════╩══════╝

但我想知道它是如何完成的没有'group by'条款。像子查询一样的东西。 我尝试了不同的东西,但我无法弄清楚它是如何工作的。我总是以结果为结尾,例如所有值总结为一行或结果如上所述但没有分组。

可能有人可以帮助我

问候

编辑:忘记了总和()

2 个答案:

答案 0 :(得分:2)

要使用GROUP BY使您当前的SQL工作,您需要以下内容(即SUM聚合函数): -

select     NAME, SUM(BAL)
from VS, BALANCE 
WHERE VS.V_ID = BALANCE.V_ID
group by NAME

请注意,这只是您最初修改的原始SQL,它仍然使用您编码的隐式连接。通常应该避免使用隐式连接,并且最好使用显式的INNER JOIN .... ON语法: -

select NAME, SUM(BAL)
from VS
INNER JOIN BALANCE 
ON VS.V_ID = BALANCE.V_ID
group by NAME

如果你真的想避开GROUP BY那么可以使用子查询,但可能会更慢(因为它实际上必须对主查询返回的每一行执行额外的查询): -

select NAME, (SELECT SUM(BAL) FROM BALANCE WHERE BALANCE.V_ID = VS.V_ID)
from VS

编辑,以回应您对子查询的评论。

相关的子查询有效地强制MySQL获取结果集,然后对结果集中的每一行执行另一个查询。大多数情况下,它们用于获取聚合值(例如,与返回行上的行相关的字段的最大值,但主查询上的GROUP BY不可行)。

例如,如果您有一个用户的评论列表,但在每一行上您想知道该用户的最新评论的日期,您可以执行以下操作: -

SELECT users.user_name, comments.comment_date, (SELECT MAX(comment_date) FROM comments WHERE comments.user_id = users.id) AS latest_comment_date
FROM users
INNER JOIN comments
ON users.id = comments.user_id

这可以编写为使用GROUP BY进行非相关的子查询,然后加入: -

SELECT users.user_name, comments.comment_date, latest_comment_date
FROM users
INNER JOIN comments
ON users.id = comments.user_id
INNER JOIN
(
    SELECT user_id, MAX(comment_date) AS latest_comment_date
    FROM comments
    GROUP BY user_id
) sub1
ON users.id = sub1.user_id

如果您正在处理大量用户记录,这可能会更快。

但是,如果您只处理用户上的少量记录(并确定该数字非常复杂),那么获取所有最大注释日期将是不必要的开销,并且它会强制针对不是&的子查询进行连接。 #39; t可能会使用索引。

答案 1 :(得分:-1)

尝试加入表:

select NAME,BAL from VS JOIN BALANCE ON VS.V_ID = BALANCE.V_ID

将返回

NAME  |  BAL
-------------
 Carl |  1000
 Carl |  500
 Carl |  -200
 Peter|  350
 Peter|  1000

要获得BAL的总和,您必须使用GROUP BY,否则您将获得所有行的SUM