HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Joining and filtering two sets of the same table

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
samethetwoandsetstablejoiningfiltering

Problem

I guess this is an easy and stupid question. Consider this MySQL 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:

  • p_id is 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.