patternsqlMinor
Joining and filtering two sets of the same table
Viewed 0 times
samethetwoandsetstablejoiningfiltering
Problem
I guess this is an easy and stupid question. Consider this MySQL
What's an appropriate way (query) to get the rows where the users whose ids are 1 and 2 have purchased the same items, and only retrieved their last purchase of those items?
The result should be something like this:
purchase table (where p_id is autoincremented):+---------+-------------+---------------+---------+
| p_id | item_id | user_id | count | ...
+---------+-------------+---------------+---------+
| 1 | 4 | 1 | 22|
| 2 | 4 | 2 | 1|
| 3 | 1 | 1 | 1|
| 4 | 0 | 3 | 1|
| 5 | 3 | 1 | 182|
| 6 | 0 | 4 | 1|
| 7 | 3 | 2 | 7|
| 8 | 3 | 2 | 14|
+---------+-------------+---------------+---------+What's an appropriate way (query) to get the rows where the users whose ids are 1 and 2 have purchased the same items, and only retrieved their last purchase of those items?
The result should be something like this:
+---------+-------------+---------------+---------+
| p_id | item_id | user_id | count | ...
+---------+-------------+---------------+---------+
| 1 | 4 | 1 | 22|
| 2 | 4 | 2 | 1|
| 5 | 3 | 1 | 182|
| 8 | 3 | 2 | 14|
+---------+-------------+---------------+---------+Solution
Assuming:
SQL Fiddle
MySQL 5.5.32 Schema Setup:
Query 1:
Results:
p_idis unique
- 'last purchase' is defined by highest
p_id
SQL Fiddle
MySQL 5.5.32 Schema Setup:
create table t(p_id integer, item_id integer, user_id integer, cnt integer);
insert into t(p_id, item_id, user_id, cnt) values(1,4,1,22);
insert into t(p_id, item_id, user_id, cnt) values(2,4,2,1);
insert into t(p_id, item_id, user_id, cnt) values(3,1,1,1);
insert into t(p_id, item_id, user_id, cnt) values(4,0,3,1);
insert into t(p_id, item_id, user_id, cnt) values(5,3,1,182);
insert into t(p_id, item_id, user_id, cnt) values(6,0,4,1);
insert into t(p_id, item_id, user_id, cnt) values(7,3,2,7);
insert into t(p_id, item_id, user_id, cnt) values(8,3,2,14);Query 1:
select *
from( select *
from t tt
where user_id=1 and p_id=( select max(p_id)
from t
where user_id=1 and item_id=tt.item_id )
union all
select *
from t tt
where user_id=2 and p_id=( select max(p_id)
from t
where user_id=2 and item_id=tt.item_id ) ) u
where item_id in(select item_id from t where user_id=1)
and item_id in(select item_id from t where user_id=2)Results:
| P_ID | ITEM_ID | USER_ID | CNT |
|------|---------|---------|-----|
| 1 | 4 | 1 | 22 |
| 5 | 3 | 1 | 182 |
| 2 | 4 | 2 | 1 |
| 8 | 3 | 2 | 14 |Code Snippets
create table t(p_id integer, item_id integer, user_id integer, cnt integer);
insert into t(p_id, item_id, user_id, cnt) values(1,4,1,22);
insert into t(p_id, item_id, user_id, cnt) values(2,4,2,1);
insert into t(p_id, item_id, user_id, cnt) values(3,1,1,1);
insert into t(p_id, item_id, user_id, cnt) values(4,0,3,1);
insert into t(p_id, item_id, user_id, cnt) values(5,3,1,182);
insert into t(p_id, item_id, user_id, cnt) values(6,0,4,1);
insert into t(p_id, item_id, user_id, cnt) values(7,3,2,7);
insert into t(p_id, item_id, user_id, cnt) values(8,3,2,14);select *
from( select *
from t tt
where user_id=1 and p_id=( select max(p_id)
from t
where user_id=1 and item_id=tt.item_id )
union all
select *
from t tt
where user_id=2 and p_id=( select max(p_id)
from t
where user_id=2 and item_id=tt.item_id ) ) u
where item_id in(select item_id from t where user_id=1)
and item_id in(select item_id from t where user_id=2)| P_ID | ITEM_ID | USER_ID | CNT |
|------|---------|---------|-----|
| 1 | 4 | 1 | 22 |
| 5 | 3 | 1 | 182 |
| 2 | 4 | 2 | 1 |
| 8 | 3 | 2 | 14 |Context
StackExchange Database Administrators Q#53913, answer score: 3
Revisions (0)
No revisions yet.