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_id
s 生成结果:
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)的主要内容,如果未能解决你的问题,请参考以下文章