Reputation: 2687
I have three tables: User, Product and Purchase
User: id, email
Product: id, name
Purchase: user_id, product_id, transaction_id
The idea is that I can find out for any given user which products he has purchased so that (in my view) I can loop over all the products and indicate which ones have been purchased already by that user. For the purchased products, I would present 'watch this product', for all other I want to display 'purchase this product'.
Right now I'm using the following query, this is to retrieve the list of products for a given user
select p1.product_id as id, p2.name, p2.price, u1.id as user_id, p1.stripe_transaction_id
from users u1
right join purchases p1 on u1.id = p1.user_id and u1.id = <user_id>
right join products p2 on p1.product_id = p2.id
Based on this, I get the following:
+------+---------------------+-------+---------+-----------------------+
| id | name | price | user_id | stripe_transaction_id |
+------+---------------------+-------+---------+-----------------------+
| 100 | Product 1 | 1999 | 3 | _jbshvScW_8961 |
| 100 | Product 1 | 1999 | NULL | _zrtdXU_6811 |
| 101 | Product 2 | 1999 | 3 | _zvgvKS_2536 |
| 102 | Product 3 | 1999 | NULL | _asgvMP_6811 |
| 103 | Bundle all products | 4999 | NULL | _bffgMXX_6811 |
+------+---------------------+-------+---------+-----------------------+
The problem with this query is that it is giving me back multiple entries for product_id (if more people have purchased that product is will display a line with product_id and user_id is NULL). In this particular example, another user has also purchased product with id 100.
Ideally I get to the following (per user):
+------+---------------------+-------+-----------+-----------------------+
| id | name | price | purchased | stripe_transaction_id |
+------+---------------------+-------+-----------+-----------------------+
| 100 | Product 1 | 1999 | false | _zrtdXU_6811 |
| 101 | Product 2 | 1999 | true | _zvgvKS_2536 |
| 102 | Product 3 | 1999 | false | _asgvMP_6811 |
| 103 | Bundle all products | 4999 | false | _bffgMXX_6811 |
+------+---------------------+-------+-----------+-----------------------+
Been trying already a while but not getting there. Any help is appreciated!
Upvotes: 1
Views: 1928
Reputation: 39
select prod.product_id as id, prod.product_name as name, prod.price as price,
case when u.user_id is null then 'false' else 'true' end as pruchased,p.transcation_id
from products prod left join purchases p on p.product_id=prod.product_id
left join users u on u.user_id = p.user_id and u.user_id=101;
Upvotes: 0
Reputation: 4052
As I understand, you want to input a user_id and get an output of every product they could have purchased, and if they did.
If that's so, you could CROSS JOIN users to products, then fill-in purchase data from purchases. But CROSS JOINs are dangerous and easy to muck up, so I avoid.
Instead, why not just use product data and fill in with purchase data?
SELECT
p.id as product_id
,p.name
,p.price
,r.stripe_data
FROM products p
LEFT JOIN purchases r ON p.id = r.product_id AND r.user_id = <your user>
This assumes a user can only purchase a product once though.
Upvotes: 2
Reputation: 957
You can use a nested query, rather than the right join, like the following:
select * from products where product_id in (select product_id from purchase where user_id = <user_id>)
You can also customize the resulted view as you like to get the prices and the other data.
Upvotes: 0