首页 > 解决方案 > 需要避免 join 中的乘法 sum()

问题描述

我的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      |
+-------+---------------------+-------------+----------------+------------+---------------------+-------------+

标签: mysqlsqlsuminner-joinaggregate-functions

解决方案


对于给定的供应商/发票元组,两个表中都有几行,因此连接乘以行,并且您在聚合函数中得到错误的结果。

您需要先在子查询中预先聚合,然后加入:

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您可以通过在查询末尾添加子句轻松更改查询以过滤给定的供应商名称。


推荐阅读