tags:

views:

38

answers:

2

I'm trying to write a query that will display the minimum value (lowest score) for each hole eliminating any duplicates. In other words, if the minimum score is 3 on hole_num 1 and there are two or more scores with 3, none of the rows corresponding to hole_num 1 should be returned. However, if there is only one value of 3 on hole_num 1 and it is the minimum value, the row should be returned. Here is what I was able to come up with... unfortunately I can't figure out how to remove the duplicates.

sample table:

player_id     hole_num     score
------------- ------------ ----- 
1             1            4
1             2            5
2             1            3
2             2            5

my query that gets the minimum score for each hole_num (but does not eliminate the row if it occurs more than once):

select. r.player_id, r.hole_num, r.score
  from scorecard_test r
  join (select hole_num, 
               min(score) best
          from scorecard_test 
      group by hole_num) v on r.hole_num = v.hole_num
                          and r.score = v.best

produces the following output:

player_id  hole_num  score 
---------- --------- ----- 
1          2         5 
2          1         3
2          2         5

I'm trying to write a query that would only display the second row above (score=3) since 5 on hole_num 2 (although it is minimum) is a repeat. Any help would be greatly appreciated.

A: 

You might be looking for this: http://www.w3schools.com/sql/sql_distinct.asp

Doing SELECT DISTINCT ... should return a single row for all that are complete duplicates.

phreakocious
The player_id value in the example are distinct - so using `DISTINCT` will have no effect unless the column is omitted from the SELECT clause.
OMG Ponies
It seemed from the description that a single row for each value of hole_num was desired.
phreakocious
Ah, I see what you mean... That would require another layer of SELECT.
phreakocious
+1  A: 

A MySQL specific solution is to add a GROUP BY and HAVING COUNT(*) = 1 to your current query:

SELECT r.player_id, r.hole_num, r.score
FROM scorecard_test r
JOIN
(
    SELECT hole_num, MIN(score) best
    FROM scorecard_test
    GROUP BY hole_num
) v
ON r.hole_num = v.hole_num AND r.score = v.best
GROUP BY hole_num, score
HAVING COUNT(*) = 1

A solution that would work more generally is to add one more join to find the unique rows:

SELECT r1.player_id, r1.hole_num, r1.score
FROM scorecard_test r1
JOIN
(
    SELECT hole_num, MIN(score) best
    FROM scorecard_test
    GROUP BY hole_num
) v
ON r1.hole_num = v.hole_num AND r1.score = v.best
LEFT JOIN scorecard_test r2
ON r1.hole_num = r2.hole_num AND r1.player_id != r2.player_id AND r1.score = r2.score
WHERE r2.player_id IS NULL

The result in both cases is this:

player_id  hole_num  score 
---------- --------- ----- 
2          1         3
Mark Byers
I was so close... exactly what I was looking for. I don't get a chance to use sql/mysql often but I find this stuff facinating for some reason... I spent the entire day constructing this query before I got stuck on the last part - thank you for taking it across the finish line for me.
Dan