tags:

views:

238

answers:

6

This question is complicated so examples would work best...I have the following table on ODBC, not SQL server Management

NAME     SEQNUM     

JOHN     2          
JOHN     4
JOHN     7
MARY     12
MIKE     4
MIKE     9
PETER    7
PETER    12

So, i want to pull back one name with the lowest seqNum...

NAME     SEQNUM
JOHN     2
MARY     12
MIKE     4
PETER    7

This data will not work with SELECT (MIN(SEQNUM)). That returns a number. I want the actual data to put in my dataset. Does ANYONE know how to do that?

+2  A: 
SELECT TOP 1 Name, SeqNum FROM yourtable ORDER BY SeqNum DESC

Will display the one with highest SeqNum

Richard L
Lowest can be gotten by switching the sort order
cdeszaq
You will only get 1 row with 1 name, not all the names as needed
Eduardo Molteni
That would work with sql server mgt. I am using odbc
You can specify such a query within an ODBC connection...
Dems
+14  A: 
select Name, MIN(SEQNUM)
from TABLE
Group By Name
Ian Jacobs
min(seqnum) retruns a number... is there another way that you are aware of?
but his select also uses select name, so you get the text field you're looking for as well
Patrick Harrington
Another way to get the minimum without a number? I'm not sure what you mean.
Ian Jacobs
MIN(SEQNUM) as SeqNum will give you a columnname. And then you can acces it by name in a dataset or simular..
Richard L
A: 
SELECT t1.*
FROM yourtable t1
 LEFT OUTER JOIN yourtable t2 
 ON (t1.name = t2.name AND t1.seqnum > t2.seqnum)
WHERE t2.seqnum IS NULL;


Re. Dems' comment:

If you simply use GROUP BY name then your select-list can only include name and the aggregate function MIN(). It's often the case that you really want the whole row where the minimum value occurs per group.

If you use the TOP solution (or LIMIT if you use MySQL, PostgreSQL, SQLite), then you can't get the minimum for multiple groups based on name, you can only get the minimum for one name.

I read between the lines of the OP's question and guessed that they want the whole row, that there are more columns than those shown in the question (there always are), and that the desired query should return results for multiple names, not just one.


Re. SquareCog's comment:

The solution you suggest is also a join:

SELECT t1.*
FROM yourtable t1
  JOIN (SELECT name, MIN(seqnum) AS seqnum FROM yourtable GROUP BY name) t2
  USING (name, seqnum);

However, this solution probably can't use indexes to evaluate the join, whereas the solution I gave can.

Bill Karwin
This seems grossly overly complicated compared to other suggestions here (Ian Jacobs if a SET is required, Richard L if a single record is required) Why is this preferable to either of those?
Dems
Bill, the cardinality of a "greater-then" join is exponential wrt number of repeats. Better to use Ian's query as the inner relation, and join on name and seqnum.
SquareCog
@SquareCog: You're using the terms "cardinality" and "exponential" incorrectly. Even a cross-product is O(n^2), i.e. polynomial.
Bill Karwin
Doh. You are correct of course. The point about inefficiency of forcing a join like that remains, though.
SquareCog
@SquareCog: I see your point but your suggestion solution is also a join. We should not shy away from joins in SQL -- that's how the language is supposed to be used.
Bill Karwin
My suggestion is an equijoin, which is significantly cheaper, computationally, than a non-equijoin (unless we are in MySQL land and all we ever do is nested loops...)
SquareCog
regarding indexes -- I am no expert on MS SQL either, but I can guarantee you that Oracle does use indexes in this case, since they are still available for the outer relation.
SquareCog
+3  A: 

I believe this is what you want:

select NAME, min(SEQNUM) as SEQNUM
from TABLE
group by NAME
Oops, turns out the first answer was too complex. This simple group by should be enough for your needs.
A: 

select name from table t where seq_num = (select max(sequnum) from table tt where t.name = tt.name)

But I like the grouping one better.

Arkadiy
+1  A: 

Bringing Ian's and Bill's answers together gives you the best of both worlds -- access to the complete record, and not having to do a potentially very expensive join (any join that's not an equijoin can blow things up like you wouldn't believe).

SELECT t1.* 
FROM yourtable t1,
     (SELECT name, MIN(seqnum) as seqnum
      FROM yourtable
      GROUP BY name) t2
WHERE t1.name=t2.name
      AND t1.seqnum=t2.seqnum

You can also use the join syntax to achieve the same result (instead of the WHERE), but in this case I think it's a little clearer what's going on if you use a where.

SquareCog
Well I'm not an expert on the MS SQL Server optimizer but it seems to me that a join on a derived table isn't likely to be able to make use of an index on seqnum. For calculating the MIN() yes perhaps, but then to do the join I wouldn't expect so.
Bill Karwin
That is to say I would expect indexed lookups to help performance more than non-equijoins harm performance.
Bill Karwin