Pergunta

Im trying to get the SUM of all user balances in a specific month, and grouped by the user's region, which depends on the Point of Sell they work at.

balance

  • id_balance
  • date
  • id_user
  • value ($$$)

user

  • id_user
  • id_pos
  • name (not relevant)

pos (Point of Sell)

  • id_pos
  • id_region
  • name (not relevant)

location_region

  • id_region
  • name (Florida, Texas, etc)

Basically, I would need it to present this data (filtered by month):

location_region.name | SUM(balance.value)
---------------------|-------------------
Florida              | 45730
Texas                | 43995

I've tried a few approaches with no luck. This was my closest attempt.

SELECT location_region.name, SUM(balance.value) AS money
FROM balance
LEFT JOIN user ON user.id_user
LEFT JOIN pos ON pos.id_pos = user.id_pos
LEFT JOIN location_region ON location_region.id_region = pos.id_region
WHERE balance.date BETWEEN '2014-02-01' AND DATE_ADD('2014-02-01', INTERVAL 1 MONTH)
GROUP BY location_region.id_region
ORDER BY money DESC

Any ideas? Thanks!

Foi útil?

Solução

Your current query has a logical error, JOIN condition between balance and user tables is incomplete (missing balance.id_user). So instead of balance LEFT JOIN user ON user.id_user you should have balance LEFT JOIN user ON user.id_user=balance.id_user. This is causing the JOINed table to have more rows (number of rows in balance times number of rows in user table). So the final SUM is bringing a way too higher value.

I tried the following query on your sample data (I changed some values) and it seems to be working fine:

SELECT location_region.name, SUM(balance.value) AS money
FROM balance
LEFT JOIN user USING(id_user)
LEFT JOIN pos USING(id_pos)
LEFT JOIN location_region USING(id_region)
WHERE balance.date BETWEEN '2014-02-01' AND DATE_ADD('2014-02-01', INTERVAL 1 MONTH)
GROUP BY location_region.id_region
ORDER BY money DESC

Working demo: http://sqlfiddle.com/#!2/dda28/3

Outras dicas

On having a detailed look at your table structure and the query that you gave, what I feel is this mismatch could happen because of duplicate number of rows that might be cropping up due to the JOIN. What I suggest in this case is to find the DISTINCT rows and summing it up so that you get an exact result. Now since SUM DISTINCT is not available in MySQL, you could try this different approach to accomplish what you want:

SELECT location_region.name, 
SUM(balance.value)*COUNT(DISTINCT id_user)/COUNT(id_user) AS money
FROM balance
LEFT JOIN user ON user.id_user = balance.id_user
LEFT JOIN pos ON pos.id_pos = user.id_pos
LEFT JOIN location_region ON location_region.id_region = pos.id_region
WHERE balance.date BETWEEN '2014-02-01' AND DATE_ADD('2014-02-01', INTERVAL 1 MONTH)
GROUP BY location_region.id_region
ORDER BY money DESC

In my comment, was wondering why u did not JOIN user table with ON clause as user.id_user = balance.id_user. I have added that however in my query. Hope this helps.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top