如何通过内部连接使用 group by

Posted

技术标签:

【中文标题】如何通过内部连接使用 group by【英文标题】:how to use group by with inner join 【发布时间】:2017-05-19 16:02:26 【问题描述】:

我有三张表customerbargainsinstallment。 我想从 customer 表中选择 name 并从 bargains 表中选择 total price 的总和以及 的总和根据每个客户从分期付款表中的付款金额,最后从付款金额的总和中减去总价格的总和。 所以结果应该是一个包含所有客户名称及其债务的列表。

我尝试了以下命令,但它返回错误的值,看起来它们相加了两次或更多。

select c.name, b.total_price, i.payment_amount
from customer as c
inner join (select sell_or_buy, sum(total_price) as total_price from     bargains group by C_ID ) as b on (b.sell_or_buy = 'خرید')
inner join (select trade_type, sum(payment_amount) as payment_amount from installment group by C_ID ) as i on (i.trade_type = 'پرداخت')
group by c.C_ID

因为我认为查询总和每条分期付款表记录的总价格和总和每条讨价还价表记录的付款金额我尝试在内部连接中使用选择来使它们中的每一个都不同但它不起作用 所以我什至无法减去结果。 我也尝试以下查询

select
(select sum(payment_amount) as payment_amount from installment  where trade_type = 'پرداخت'group by C_ID)-
(select sum(total_price) as total_price from bargains where sell_or_buy = 'خرید' group by C_ID)as result

表示查询返回多行的显示和错误。 当我从上面的查询中只使用一个选择时,结果是好的,但是当我尝试组合它时它不起作用。

【问题讨论】:

【参考方案1】:

您的原始查询似乎缺少正确的连接条件。试试这个:

select c.name,
       b.total_price,
       i.payment_amount
from customer as c
inner join
(
    select C_ID, sum(total_price) as total_price
    from bargains
    where sell_or_buy = 'خرید'
    group by C_ID
) as b
    on c.C_ID = b.C_ID
inner join
(
    select C_ID, sum(payment_amount) as payment_amount
    from installment
    where trade_type = 'پرداخت'
    group by C_ID
) as i
    on c.C_ID = i.C_ID

如果你想计算总价和支付金额之间的差额,那么就用这个SELECT

select c.name,
       b.total_price,
       i.payment_amount,
       b.total_price - i.payment_amount AS diff

【讨论】:

我只想知道哪个更好,减去这两个内部连接在 sql 中的结果,这样我就有两列作为结果(客户名称和债务),正如我提到的问题或当我在 php 中接收查询结果,然后在循环中逐行减去它们。如果第一选择更好,那么我应该怎么做,因为我是 sql 新手,但我可以在 php 中做到这一点【参考方案2】:

不需要使用子查询,只需将三张表连接起来做聚合,试试如下:

select 
    c.name,
    sum(b.total_price) as total_price,
    sum(i.payment_amount) as payment_amount
from customer as c
inner join bargains b on c.c_id = b.c_id and b.sell_or_buy = 'خرید'
inner join installment i on c.c_id = i.c_id and i.trade_type = 'پرداخت'
group by c.c_id   -- ,c.name

就像@Tim Biegleisen 所说,如果您的mysql 数据库的sql_mode 包含ONLY_FULL_GROUP_BY,您还应该在group by 子句中添加c.name。 并使用此查询检查sql_mode

show variables like 'sql_mode';

【讨论】:

【参考方案3】:

你能给我一张每个表的实际屏幕截图,其中包含一些条目吗?

由于这一行,您可能会得到重复的行: inner join (select trade_type, sum(payment_amount) as payment_amount from installment group by C_ID )

基本上,您可能不应该使用 sum() 函数同时从任何其他字段中选择值。原因如下: sum(payment_amount) 应该正确返回 1 行?但是在它旁边你有“select trade_type”,它可能会返回多行。

另外,这是什么语言? MySQL? SQL?

【讨论】:

【参考方案4】:

子查询:

SELECT c.Id AS CustomerId, c.Name AS CustomerName, m.Name AS ManagerName, o.SumAmmount 
FROM Customers AS c
INNER JOIN Managers AS m ON c.ManagerId = m.Id
INNER JOIN 
(SELECT SUM(Amount) AS SumAmmount, o.CustomerId
 FROM Orders AS o
 WHERE Date >= '2017-01-01'
 GROUP BY CustomerId
 HAVING SUM(Amount) >= 10000) AS o ON c.Id = o.CustomerId

没有子查询:

SELECT c.Id AS CustomerId, c.Name AS CustomerName, 
       m.Name AS ManagerName, SUM(o.Amount) AS SumAmmount 
FROM Customers AS c
INNER JOIN Managers AS m ON c.ManagerId = m.Id
INNER JOIN Orders AS o ON c.Id = o.CustomerId
WHERE o.Date >= '2017-01-01'
GROUP BY c.Id, c.Name, m.Name
HAVING SUM(Amount) >= 10000

【讨论】:

以上是关于如何通过内部连接使用 group by的主要内容,如果未能解决你的问题,请参考以下文章

Mysql group by 具有不同的和内部连接

MYSQL group by 和内部连接

如何连接具有不同 GROUP BY 级别的两个查询,使一些记录为空

如何通过自我加入使用 group by

如何在 PostgreSQL 'group by' 查询中连接字符串字段的字符串?

如何通过 group_by 中的 group-number 对数据表进行编号/标记?