0

I sort the rows on date. If I want to select every row that has a unique value in the last column, can I do this with sql?

So I would like to select the first row, second one, third one not, fourth one I do want to select, and so on.

enter image description here

Veltar
  • 741
  • 2
  • 14
  • 30
  • "only select the row if the field value is unique" Err.. the first row has value 28 but this is not unique. – Mark Byers May 08 '12 at 12:46
  • What unique value do you mean (table and column)? – gbn May 08 '12 at 12:46
  • 3
    In future, if you post the SQL query as text, not an embedded image, it makes it *much* easier for people to help you, as we can then just copy'n'paste the query, instead of having to re-type it. – Cylindric May 08 '12 at 13:00

3 Answers3

3

What you want are not unique rows, but rather one per group. This can be done by taking the MIN(pk_artikel_Id) and GROUP BY fk_artikel_bron. This method uses an IN subquery to get the first pk_artikel_id and its associated fk_artikel_bron for each unique fk_artikel_bron and then uses that to get the remaining columns in the outer query.

SELECT * FROM tbl 
WHERE pk_artikel_id IN
  (SELECT MIN(pk_artikel_id) AS id FROM tbl GROUP BY fk_artikel_bron)

Although MySQL would permit you to add the rest of the columns in the SELECT list initially, avoiding the IN subquery, that isn't really portable to other RDBMS systems. This method is a little more generic.

It can also be done with a JOIN against the subquery, which may or may not be faster. Hard to say without benchmarking it.

SELECT * 
FROM  tbl
  JOIN (
    SELECT 
      fk_artikel_bron, 
      MIN(pk_artikel_id) AS id
    FROM tbl
    GROUP BY fk_artikel_bron) mins ON tbl.pk_artikel_id = mins.id
Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
  • your subquery returns more than one column so you cannot use it with a `WHERE ... IN ( ... )` condition. Remove `fk_artikel_bron` from the resultset in your subquery to fix this. – Kaii May 08 '12 at 12:52
  • @ŁukaszW.pl The `GROUP BY` will supply multiple records in the subquery, and all of them will will be passed to the outer query. – Michael Berkowski May 08 '12 at 12:55
2

This is similar to Michael's answer, but does it with a self-join instead of a subquery. Try it out to see how it performs:

SELECT * from tbl t1
LEFT JOIN tbl t2
  ON t2.fk_artikel_bron = t1.fk_artikel_bron
  AND t2.pk_artikel_id < t1.pk_artikel_id
WHERE t2.pk_artikel_id IS NULL

If you have the right indexes, this type of join often out performs subqueries (since derived tables don't use indexes).

Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
-1

This non-standard, mysql-only trick will select the first row encountered for each value of pk_artikel_bron.

select *
...
group by pk_artikel_bron

Like it or not, this query produces the output asked for.

Edited

I seem to be getting hammered here, so here's the disclaimer:

This only works for mysql 5+

Although the mysql specification says the row returned using this technique is not predictable (ie you could get any row as the "first" encountered), in fact in all cases I've ever seen, you'll get the first row as per the order selected, so to get a predictable row that works in practice (but may not work in future releases but probably will), select from an ordered result:

select * from (
    select *
    ... 
    order by pk_artikel_id) x
group by pk_artikel_bron
Community
  • 1
  • 1
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 1
    This one is not a good way to do that, because you should not select columns that are not grouping key (in this case you select all, but grouping only by last_column) – Łukasz W. May 08 '12 at 12:51
  • 1
    @ŁukaszW.pl But this is mysql, and THIS WORKS! – Bohemian May 08 '12 at 12:51
  • 1
    @ŁukaszW.pl I sued to think that way too, but I have gone over to the dark side... this mysql-only funk is *really* handy, and so simple to code! – Bohemian May 08 '12 at 12:53
  • 2
    @Bohemian: It doesn't work **RELIABLY**. See http://stackoverflow.com/a/6642253/27535 for a simple example. And here too: http://stackoverflow.com/a/7444144/27535 – gbn May 08 '12 at 12:58
  • 1
    @Bohemian, for the record, I didn't down vote. It's a legitimate answer, but you should explain consequences of this (arbitrary values) and MySQL 5.+ limitation. :) – Marcus Adams May 08 '12 at 12:59