简体   繁体   中英

mysql sum() two joined tables, multiplies result

i have two tables; invoices & invoiceitems.
invoiceitems contains the items on each invoice

eg:

invoices
----------------------------------
| id  |status| net | tax | total |
----------------------------------
| 72  |paid  | 100 | 120 |  220  |
| 73  |unpaid| 50  | 5   |  55   |
| 74  |paid  | 400 | 45  |  445  |
| 75  |paid  | 250 | 67  |  317  |


invoiceitems
-------------------------------
| invoiceid |itemdescription |
-------------------------------
| 72        | apples         |
| 72        | pears          |
| 72        | oranges        |
| 73        | lemons         |
| 73        | oranges        |

as you can see, in the example invoice number 72 has 3 items

i want to search my invoices for certain things, and display a count of certain fields.

but my problem is that the sum value seems to get multiplied by the number of fields there are in the second table.

$sql = "SELECT COUNT(DISTINCT invoices.id) AS num, 
SUM(CASE invoices.status WHEN 'Paid' THEN 1 ELSE 0 END) AS numpaid, 
SUM(CASE invoices.status WHEN 'Paid' THEN invoices.total ELSE 0 END) AS sumtotal,
FROM invoices 
LEFT JOIN invoiceitems ON invoices.id=invoiceitems.invoiceid
WHERE invoices.id LIKE :invoiceid 
AND IFNULL(opcinvoiceitems.itemdescription, '')  LIKE :itemdescription
AND invoices.net LIKE :net 
AND invoices.tax LIKE :tax 
AND invoices.total LIKE :total
AND ......" 

so using the above, the total for invoice 72 would be multiplied by 3

i'm really sorry, i know this is really badly explained but i cant explain it any other way, been searching for ages but cant find a solution. hope someone can help. thanks

When you do a join, you produce records created by matching up ones from the original tables. Thus, you will have 3 records for invoice #72, each created by matching up the single invoices record for #72 with each of the invoice items for #72. Each combined record will have the same total (in this case, 220), and thus the sum would be 3 times that.

It sounds like you just want total, then; you could just use total directly, or you could take your sum and divide it by the count (which you appear to also be computing).

One way to do what you want is to pre-aggregate the invoiceItems table before joining:

SELECT COUNT(i.id) AS num, 
       SUM(CASE i.status WHEN 'Paid' THEN 1 ELSE 0 END) AS numpaid, 
       SUM(CASE i.status WHEN 'Paid' THEN i.total ELSE 0 END) AS sumtotal,
FROM invoices  i LEFT JOIN
     (select ii.invoiceid, sum(. . .) as . . .
      from invoiceitems ii
      where IFNULL(ii.itemdescription, '')  LIKE :itemdescription AND
      group by ii.invoiceid
     ) ii
     ON i.id = ii.invoiceid
WHERE i.id LIKE :invoiceid AND
      i.net LIKE :net  AND
      i.tax LIKE :tax AND
      i.total LIKE :total AND .....

Your query doesn't actually use invoiceitems in the from clause, so it is hard to provide a more detailed example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM