tim peterson
tim peterson

Reputation: 24305

MYSQL SUM() in one table and JOIN with 2 other tables

I have 3 tables: items, purchases, and collaborators. A user can own an item, purchase an item, or be a collaborator on an item. Additionally, items that are purchased can be rated up, +1, or down, -1. An owner or collaborator can't purchase their own item.

I'd like to get all items for a given user and also display the ratings on each item.

Here's my tables:

      items           |           purchases           |     collaborators
i_id  item_id user_id | p_id item_id  user_id  rating |c_id item_id user_id
  1      1       11   |  1      1         13     -1   |  1     1        12 
  2      2       12   |  2      2         11      1   |  2     2        13
  3      3       13   |  3      3         12     NULL |    
                      |  4      1         14     -1   |

Here's my MYSQL query so far:

select *, count(p_id) as tots, sum(rating=1) as yes, sum(rating= '-1') as no
from items
left join purchases
on items.item_id=purchases.item_id
left join collaborators
on items.item_id=collaborators.item_id
where items.user_id=13 or purchases.user_id=13 or collaborators.user_id=13
group by items.item_id

Here's my expected results for user_id=11 (changing each user_id in the WHERE clause):

item_id    tots  yes no
  1         2     0   2
  2         1     1   0
// notice how user_id=11 doesn't have anything to do with item_id=3

Here's my expected results for user_id=12:

item_id    tots  yes no
  1         2     0   2
  2         1     1   0    
  3         1     1   0  

Here's my expected results for user_id=13:

item_id    tots  yes no
  1         2     0   2
  2         1     1   0    
  3         1     1   0   
//notice user_id=13 should have same results as user_id=12. Although, their 
relation to each of the 3 items is different, they still either purchased, 
own, or collaboratored on each of them.

Unfortunately, I get the first two results but not the correct one for user_id=13. For user_id=13, item_id=1 the tots=1 and not tots=2 for some reason I can't understand.

Any thoughts, such as, "its better to separate this into 2 queries", would be greatly appreciated,

Upvotes: 2

Views: 717

Answers (1)

Lieven Keersmaekers
Lieven Keersmaekers

Reputation: 58431

I'm still not entirly sure I understand you correct but you could try following statement and let us work from there.

Edit

Following statement returns the expected results.
You can verify this (using SQL Server) here.

The gist of this is to

  • select all possible user_id and item_id combinations from your three tables
  • select the counts/ratings for each item
  • combine the results

SQL Statement

SELECT u.user_id, pt.item_id, pt.cnt, pt.yes, pt.no
FROM   (
        SELECT user_id, item_id, title FROM items 
        UNION SELECT user_id, item_id, NULL FROM purchases
        UNION SELECT user_id, item_id, NULL FROM collaborators      
       ) u INNER JOIN (
        SELECT COUNT(*) AS cnt
               , SUM(CASE WHEN ISNULL(rating, 1) = 1 THEN 1 ELSE 0 END) AS yes
               , SUM(CASE WHEN rating =-1 THEN 1 ELSE 0 END) AS no
               , item_id
        FROM   purchases
        GROUP BY
               item_id
      ) pt ON pt.item_id = u.item_id    

MYSQL statement

SELECT u.user_id, pt.item_id, pt.cnt, pt.yes, pt.no, u.title
FROM   (
    SELECT user_id, item_id, title FROM items where user_id=13
    UNION SELECT user_id, item_id, NULL FROM purchases where user_id=13
    UNION SELECT user_id, item_id, NULL FROM collaborators where user_id=13       
   ) u INNER JOIN (
    SELECT COUNT(*) AS cnt
           , SUM(rating=1) AS yes
           , SUM(rating =-1) AS no
           , item_id
    FROM   purchases 
    GROUP BY
           item_id
  ) pt ON pt.item_id = u.item_id 

Upvotes: 1

Related Questions