tags:

views:

90

answers:

3

I have two tables A,B which are related to each other (simplified):

A:
+-------+---------+ 
| id    | type    | 
+-------+---------+ 
| 1     | apple   | 
| 2     | orange  | 
| 3     | banana  | 
+-------+---------+ 

B:
+-------+---------+-----------+ 
| id    | a_id    |  rank     |  
+-------+---------+-----------+  
| 1     | 1       |  9.9      |
| 2     | 1       |  7.7      |
| 3     | 2       |  3.3      |
| 4     | 2       |  8.8      |
| 5     | 2       |  1.1      |  
| 6     | 3       |  3.3      |
| 7     | 3       |  2.2      | 
| 8     | 1       |  0.0      | 
+-------+---------+-----------+   

What mysql query will return the following result?

Result
+-------+---------+-----------+ 
| id    | type    |  rank     |  
+-------+---------+-----------+  
| 1     | apple   |  0.0      | 
| 2     | orange  |  1.1      | 
| 3     | banana  |  2.2      | 
+-------+---------+-----------+ 

The rank that was inserted last in table B is picked (it's not MAX(rank)).

The rank in the result table needs to be picked from table B with the highest id.

+6  A: 

UPDATED

You may want to try joining with a subquery to get the MAX(id) for each a_id in table_b, and then INNER JOIN with table_b to get the rank:

SELECT   ta.id, 
         ta.type,
         tb.rank
FROM     table_a ta
JOIN     (
            SELECT   MAX(id) AS id, 
                     a_id
            FROM     table_b
            GROUP BY a_id
         ) sub_q ON (sub_q.a_id = ta.id)
JOIN     table_b tb ON (tb.id = sub_q.id)
ORDER BY ta.id;

Test case:

CREATE TABLE table_a (id int, type varchar(10));
CREATE TABLE table_b (id int, a_id int, rank decimal(2,1));

INSERT INTO table_a VALUES (1, 'apple');
INSERT INTO table_a VALUES (2, 'orange');
INSERT INTO table_a VALUES (3, 'banana');

INSERT INTO table_b VALUES (1, 1, 9.9);      
INSERT INTO table_b VALUES (2, 1, 7.7);       
INSERT INTO table_b VALUES (3, 2, 3.3);       
INSERT INTO table_b VALUES (4, 2, 8.8);      
INSERT INTO table_b VALUES (5, 2, 1.1);         
INSERT INTO table_b VALUES (6, 3, 3.3);       
INSERT INTO table_b VALUES (7, 3, 2.2);       
INSERT INTO table_b VALUES (8, 1, 0.0);      

Result:

+------+--------+------+
| id   | type   | rank |
+------+--------+------+
|    1 | apple  |  0.0 |
|    2 | orange |  1.1 |
|    3 | banana |  2.2 |
+------+--------+------+
3 rows in set (0.01 sec)
Daniel Vassallo
So he's looking for the "most recent" rank (or at least the one with the highest ID)?
Eric J.
Yes, it looks like it.
Daniel Vassallo
@Daniel: Thanks! Can you explain these: t.id, t.type, sub_t1?
Yeti
I've updated my answer with slightly more clear aliases. So you start with `SELECT id, type FROM table_a`. This will return the result set you wanted without the rank. Then we create a subquery `SELECT MAX(id) AS id, a_id FROM table_b GROUP BY a_id`. This builds a result-set that gives us the MAX(id) for each a_id. We give this sub query the alias `sub_q` and INNER JOIN our previous result-set with this subquery on `(sub_q.a_id = ta.id)`. Now we know which row in `table_b` contains the rank for each type. So we `INNER JOIN` with `table_b` on `(tb.id = sub_q.id)` to get the rank.
Daniel Vassallo
@Lost_in_code: The answers posted by [Mark Baker](http://stackoverflow.com/questions/2936853/what-mysql-query-will-return-this-result/2936950#2936950) and [Pascal Thivent](http://stackoverflow.com/questions/2936853/what-mysql-query-will-return-this-result/2936933#2936933) are similar interpretations of this query. Maybe you will find their format clearer, but I tend to prefer the one I described.
Daniel Vassallo
@Daniel: Works like a charm. I will go with yours since it was the first answer :)
Yeti
+2  A: 

What about this:

SELECT a.id, a.type, b.rank 
FROM tempa a, tempb b 
WHERE a.id = b.a_id 
  AND b.id = (
    SELECT MAX(b.id) 
    FROM tempb b 
    WHERE b.a_id = a.id
)
ORDER BY a.id;

Outputs:

1, apple, 9.50
2, orange, 1.10
3, banana, 5.50
Pascal Thivent
This query outputted a bizarre result!
Yeti
@Lost_in_code: what do you mean by bizarre? It outputs the result of the initial question, doesn't it? Of course, now that you changed the question, you invalidated my answer, but still, what do you mean by bizarre?
Pascal Thivent
@Lost_in_code: It did work on the test case I defined in my answer. (substituting `tempa` for `table_a` and `tempb` for `table_b`. What result did you get?
Daniel Vassallo
Sorry, no offense. It outputted a whole lot of extra rows, which didn't seem right. I changed the question, for better readability. Instead of 9.50,1.10,5.50 you will now see 0.0,1.1,2.2 - which would make no difference to the query (will re-check if I did something wrong)
Yeti
@Lost_in_code: No problem, it's just that bizarre result doesn't say much about what you got. But indeed, the changes you made with the values shouldn't change the query, just the result.
Pascal Thivent
@Pascal: This too works as expected. I had made some error earlier while making changes to the column names to reflect the actual table. Thanks.
Yeti
+2  A: 
SELECT a.id,
       a.type,
       b1.rank
 FROM a,
      b b1
 WHERE b1.a_id = a.id
 AND NOT EXISTS( SELECT b2.id
                  FROM b AS b2
                 WHERE b2.a_id = a.id
                   AND b2.id > b1.id
               )
 ORDER BY a.type
Mark Baker