需要避免 join 中的乘法 sum()
Posted
技术标签:
【中文标题】需要避免 join 中的乘法 sum()【英文标题】:Need to avoid the multiplies sum() in join 【发布时间】:2021-03-23 21:43:23 【问题描述】:我的 mysql 查询是...
SELECT row_number() over (order by p.invoice_number) as 'S.No.'
, p.created_at as 'invoice_date'
, p.vendor_name
, p.invoice_number
, format(sum(p.cost),0,'en_IN') as total_cost
, v.accountno as accountno
, v.paid_date as paid_date
, format(sum(v.paid_amount),0,'en_IN') as paid_amount
from purchases p
join vendor_accounts v
on p.invoice_number = b.invoice_number
group
by p.invoice_number
having p.vendor_name = 'govardhan';
+-------+---------------------+-------------+----------------+------------+-----------+---------------------+-------------+
| S.No. | invoice_date | vendor_name | invoice_number | total_cost | accountno | paid_date | paid_amount |
+-------+---------------------+-------------+----------------+------------+-----------+---------------------+-------------+
| 1 | 2020-12-12 20:12:33 | govardhan | 061067 | 79,980 | JBL | 2020-12-12 20:38:30 | 2,50,000 |
+-------+---------------------+-------------+----------------+------------+-----------+---------------------+-------------+
输出乘以 vendor_name(10 次)和另一个表 vendor_name(2 次)共 20 次
我的输出应该是这样的
+-------+---------------------+-------------+----------------+------------+-----------+---------------------+-------------+
| S.No. | invoice_date | vendor_name | invoice_number | total_cost | accountno | paid_date | paid_amount |
+-------+---------------------+-------------+----------------+------------+-----------+---------------------+-------------+
| 1 | 2020-12-12 20:12:33 | govardhan | 061067 | 39,990 | JBL | 2020-12-12 20:38:30 | 2,50,00 |
+-------+---------------------+-------------+----------------+------------+-----------+---------------------+-------------+
请帮我解决问题。提前致谢。
样本数据:
mysql> select * from purchases where vendor_name='gowri';
+------+-------------+----------+-------+---------------+----------------+---------------+----------+-------------------+-------------+-------------------+----------------+---------------------+------------+
| id | vendor_name | location | cost | cost_of_price | invoice_number | serial_number | paid_GST | profit_percentage | sales_price | tag | barcode | created_at | updated_at |
+------+-------------+----------+-------+---------------+----------------+---------------+----------+-------------------+-------------+-------------------+----------------+---------------------+------------+
| 1654 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16542012122028 | 2020-12-12 20:28:53 | NULL |
| 1655 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16552012122028 | 2020-12-12 20:28:54 | NULL |
| 1656 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16562012122028 | 2020-12-12 20:28:54 | NULL |
| 1657 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16572012122028 | 2020-12-12 20:28:54 | NULL |
| 1658 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16582012122028 | 2020-12-12 20:28:54 | NULL |
| 1659 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16592012122028 | 2020-12-12 20:28:54 | NULL |
| 1660 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16602012122028 | 2020-12-12 20:28:55 | NULL |
| 1661 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16612012122028 | 2020-12-12 20:28:55 | NULL |
| 1662 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16622012122028 | 2020-12-12 20:28:55 | NULL |
| 1663 | gowri | KPM | 2999 | 3149 | 3614 | 01 | 5 | 35 | 4251 | gowri/314/3614/01 | 16632012122028 | 2020-12-12 20:28:55 | NULL |
| 1664 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16642012122030 | 2020-12-12 20:30:21 | NULL |
| 1665 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16652012122030 | 2020-12-12 20:30:21 | NULL |
| 1666 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16662012122030 | 2020-12-12 20:30:22 | NULL |
| 1667 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16672012122030 | 2020-12-12 20:30:22 | NULL |
| 1668 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16682012122030 | 2020-12-12 20:30:22 | NULL |
| 1669 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16692012122030 | 2020-12-12 20:30:22 | NULL |
| 1670 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16702012122030 | 2020-12-12 20:30:23 | NULL |
| 1671 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16712012122030 | 2020-12-12 20:30:23 | NULL |
| 1672 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16722012122030 | 2020-12-12 20:30:24 | NULL |
| 1673 | gowri | KPM | 3999 | 4199 | 3614 | 02 | 5 | 35 | 5669 | gowri/419/3614/02 | 16732012122030 | 2020-12-12 20:30:24 | NULL |
| 1694 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 16942012130215 | 2020-12-13 02:15:55 | NULL |
| 1695 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 16952012130215 | 2020-12-13 02:15:55 | NULL |
| 1696 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 16962012130215 | 2020-12-13 02:15:55 | NULL |
| 1697 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 16972012130215 | 2020-12-13 02:15:56 | NULL |
| 1698 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 16982012130215 | 2020-12-13 02:15:56 | NULL |
| 1699 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 16992012130215 | 2020-12-13 02:15:56 | NULL |
| 1700 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17002012130215 | 2020-12-13 02:15:56 | NULL |
| 1701 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17012012130215 | 2020-12-13 02:15:56 | NULL |
| 1702 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17022012130215 | 2020-12-13 02:15:56 | NULL |
| 1703 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17032012130215 | 2020-12-13 02:15:56 | NULL |
| 1704 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17042012130215 | 2020-12-13 02:15:56 | NULL |
| 1705 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17052012130215 | 2020-12-13 02:15:56 | NULL |
| 1706 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17062012130215 | 2020-12-13 02:15:56 | NULL |
| 1707 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17072012130215 | 2020-12-13 02:15:56 | NULL |
| 1708 | gowri | JBL | 46666 | 48999 | 3615 | 01 | 5 | 35 | 66149 | gowri/489/3615/01 | 17082012130215 | 2020-12-13 02:15:56 | NULL |
+------+-------------+----------+-------+---------------+----------------+---------------+----------+-------------------+-------------+-------------------+----------------+---------------------+------------+
35 rows in set (0.00 sec)
mysql> select * from vendor_accounts where vendor_name='gowri';
+----+-------------+----------------+-----------+-------------+---------------------+
| id | vendor_name | invoice_number | accountno | paid_amount | paid_date |
+----+-------------+----------------+-----------+-------------+---------------------+
| 2 | gowri | 3614 | NULL | NULL | 2020-12-12 20:28:55 |
| 3 | gowri | 3614 | NULL | NULL | 2020-12-12 20:30:25 |
| 10 | gowri | 3614 | XXX1035 | 25000 | 2020-12-13 02:13:52 |
| 11 | gowri | 3615 | NULL | NULL | 2020-12-13 02:15:57 |
+----+-------------+----------------+-----------+-------------+---------------------+
4 rows in set (0.00 sec)
实际输出应该是这样的
+-------+---------------------+-------------+----------------+------------+---------------------+-------------+
| S.No. | invoice_date | vendor_name | invoice_number | total_cost | paid_date | paid_amount |
+-------+---------------------+-------------+----------------+------------+---------------------+-------------+
| 1 | 2020-12-12 20:28:53 | gowri | 3614 | 69,980 | 2020-12-12 20:28:55 | 5,00,000 |
| 2 | 2020-12-13 02:15:55 | gowri | 3615 | 6,99,990 | 2020-12-13 02:15:57 | NULL |
| | | | TOTAL | 7,69,970 | | 25,000 |
+-------+---------------------+-------------+----------------+------------+---------------------+-------------+
【问题讨论】:
请以表格文本形式提供示例数据和所需结果。您的查询看起来不像是有效的聚合查询。 由purchases
聚合,然后加入vendor_accounts
。
@GMB - 先生,请在下面的答案中找到编辑查询的结果和示例数据
@GowthamKrisher:这应该作为edit to your question 发布,而不是作为答案。我将相关信息复制到您的问题 - 您应该考虑删除以下答案。
@GMB 是的,先生,您的代码对我来说效果很好,感谢您的大力帮助
【参考方案1】:
对于给定的供应商/发票元组,两个表中都有几行,因此连接会乘以行,并且您会在聚合函数中得到错误的结果。
您需要先在子查询中预聚合,然后再加入:
select
row_number() over (order by p.invoice_number) as rn,
p.*,
va.total_paid_amount,
va.max_paid_date
from (
select vendor_name, invoice_number,
sum(p.cost) as total_cost,
max(created_at) as max_created_at
from purchases
group by vendor_name, invoice_number
) p
inner join (
select vendor_name, invoice_number,
sum(paid_amount) as total_paid_amount,
max(paid_date) as max_paid_date
from vendor_accounts
group by vendor_name, invoice_number
) va on va.invoice_number = p.invoice_number and va.vendor_name = p.vendor_name
请注意,我在日期列上使用了聚合函数;与您的原始查询不同。这些列不属于group by
子句,因此我们需要对它们进行聚合。
这会同时为所有供应商带来结果。您可以通过在查询末尾添加 where
子句轻松更改查询以过滤给定的供应商名称。
【讨论】:
先生,我们可以连接任何桌面吗:)以上是关于需要避免 join 中的乘法 sum()的主要内容,如果未能解决你的问题,请参考以下文章
postgreSQL计算总数sum if case when
SQL sum()后许多字段要group by不使用group by, 改用left join select 需要的字段。哪个方法好?速度快?