MySQL 和两列 (1 -> n)

Posted

技术标签:

【中文标题】MySQL 和两列 (1 -> n)【英文标题】:MySQL Sum two columns (1 -> n) 【发布时间】:2020-09-19 01:49:18 【问题描述】:

我有一个表“rents”,其中包含字段 ID 和外键 events_id 以及字段 total_value,我还有另一个表 'payments' 具有字段 ID、外键 rents_id 和字段 payment

表格事件:

ID

餐桌租金:

ID,
total_value,
events_id 

餐桌付款:

ID,
payment,
rents_id

rents 表的同一个 ID 有很多次付款,events 表的同一个 ID 有很多次租金。 我需要创建一个查询,显示在租金表中具有相同事件 ID 的字段“total_value”的 sum(),以及在付款表中具有相同租金 ID 的字段“付款”的 sum() .

我已经设法创建了完成此任务的查询:

SELECT SUM(r.total_value) 'Total Value', (SELECT SUM(p.payment) FROM payments p INNER JOIN rents r ON p.rents_id = r.id WHERE r.events_id=8) 'Total Payment'
FROM rents r
WHERE r.events_id=8
;

我想知道这是否是唯一的方法,还是有更好的方法?

【问题讨论】:

请提供样本输入,尤其是输出。 在没有完全定义“最佳”的情况下询问做事的方法或什么是“最佳”以及为什么您无法自己确定,这些都不是有效的问题。 How to Askhelp center 我的意思是:性能 + 更少的代码 + 良好的实践 这些都是模糊的。该评论没有解决我的最后评论。还请通过编辑而不是 cmets 进行澄清。并且询问事情的清单是题外话。这也反映了没有研究回答这个问题。等等Meta Stack OverflowMeta Stack Exchange 工程中没有“更好”/“最好”之类的东西,除非你定义它。同样不幸的是,所有合理的实际定义都需要大量的经验,以及与对细节的混乱敏感度相互作用的大量因素。进行简单的设计。当您通过测量证明您可以想到的设计和所有替代方案都存在问题时(无论当时意味着什么),然后提出一个非常具体的问题。这也应该定义“更好”/“最好”。 Strategy for “Which is better” questions 【参考方案1】:

我推荐一个连接 - 想法是首先在子查询中计算中间支付总和,然后连接,并在外部查询中再次聚合。

select sum(r.total_value) total_value, sum(p.payment) total_payment
from rents r
left join (
    select rents_id, sum(payment) payment from payments group by rents_id
) p on p.rents_id = r.id
where r.events_id = 8

left join 避免过滤掉根本没有付款的租金。

您可以轻松更改查询以一次为所有event_ids 生成结果:

select r.events_id, sum(r.total_value) total_value, sum(p.payment) total_payment
from rents r
left join (
    select rents_id, sum(payment) payment from payments group by rents_id
) p on p.rents_id = r.id
group by r.events_id

【讨论】:

此查询给出错误 1054:“字段列表”中的未知列“p.payment”。您在左连接后使用选择子句而不是表名。 子查询别名设置为r ..我想你的意思是设置p 它继续给出相同的错误:字段列表中的未知列“p.payment”。这是因为连接正在接收选择子句而不是表名。在我的查询中,INNER JOIN 或 LEFT JOIN 产生相同的结果,如果没有支付该租金,则 total_payment 列中为 null。 @Beto:我也修复了第二个查询中的别名。 @GMB 我知道,我也测试了第二个查询并给出错误 1054:未知列 p.payment 我认为除了我提供的查询之外没有其他方法可以显示我需要的内容,我感谢 GMB 的帮助。【参考方案2】:

相关子查询可能是最好的方法(稍后我会解释)。但是,子查询中不需要join,只需一个相关子句:

SELECT SUM(r.total_value) as Total_Value,
       (SELECT SUM(p.payment)
        FROM payments p 
        WHERE p.rents_id = r.id
--------------^ correlation clause that "links" the subquery to the outer query
       ) as Total_Payment
FROM rents r
WHERE r.events_id = 8;

为什么这是最好的方法?首先,在payments(rents_id)rests(events_id) 上有一个索引,这应该是最快的方法。

其次,注意过滤条件在查询中只包含一次。这使得更新查询变得容易并且不易出错。

第三,这不会预先汇总付款表。预聚合要么需要重复过滤条件(如您的查询版本),要么需要聚合更多的数据(这会影响性能)。

此外,我建议您不要对列别名使用单引号。仅对字符串和日期常量使用单引号。

【讨论】:

感谢 Gordon 的提示,此查询为总付款列提供 null,我的内部连接查询为 Total_Value 提供 121.25,为 Total_Payment 提供 70.50,这是两列的正确值.我认为在这种情况下加入子句是必要的。但是你已经明白我的意思了:性能 + 更少的代码 + 好的实践 @Beto 。 . .如果没有与外部查询中的r.id 匹配的付款,这只会给出NULL 值。如果是这种情况,NULL 也不会返回任何值。 您查询的 Total_Payment 为 null,但在 events_id=8 的情况下支付租金和 p.rents_id=r.id 我认为除了我提供的查询之外没有其他方法可以显示我需要的东西,我感谢 Gordon 的帮助。

以上是关于MySQL 和两列 (1 -> n)的主要内容,如果未能解决你的问题,请参考以下文章

如何将函数应用于两列 Pandas 数据框和两列 if 函数

JPA Criteria Query API 和两列排序

HTML div 跨越两列和两行

如何在日期时间索引和两列上合并熊猫数据框

如何在Pig中找到一列的平均值和两列的减法平均值?

MySQL:按两列的函数排序