tags:

views:

774

answers:

5

If I do something like

SELECT * FROM mytable ORDER BY mycolumn ASC;

I get a result table in a specific order.

Is there a way in SQL to efficiently find out, given a PK, what position in that result table would contain the record with my PK?

+2  A: 

On databases that support it, you could use ROW_NUMBER() for this purpose:

SELECT RowNr
FROM (
    SELECT 
         ROW_NUMBER() OVER (ORDER BY mycolumn) AS RowNr,
         mycolumn
    FROM mytable
) sub
WHERE sub.mycolumn = 42

The example assumes you're looking for primary key 42 :)

The subquery is necessary because something like:

SELECT 
     ROW_NUMBER() OVER (ORDER BY mycolumn) AS RowNr
FROM mytable
WHERE sub.mycolumn = 42

Will always return 1; ROW_NUMBER() works after the WHERE, so to speak.

Andomar
Why the downvote? This is correct and helpful for database engines supporting ROW_NUMBER (how speedy this is vs alternatives, as usual, requires specific measurement on a given DB).
Alex Martelli
This is a perfectly valid solution for SQL Server.
Aaron Alton
I didn't give a downvote, but fwiw the OP didn't say he was using Microsoft SQL Server. He might be, but he didn't say so or tag his question for it.
Bill Karwin
Before jumping on the downvote vagon cuz is 'm$ specific' take a minute and RTFM. ROW_NUMBER, RANK, DENSE_RANK, PERCENT_RANK and CUME_DIST are the windowing functions specified in the ANSI standard SQL-2003 and all major vendors support them or plan to support them soon.
Remus Rusanu
The problem with row-number is that it doesn't give you the "position in the table". It gives you the position in that specific result-set. It might be what the person asking wants, but it doesn't really answer the question as asked.
Lasse V. Karlsen
He says 'result table', I interpret that as 'result set'
Remus Rusanu
@Lasse V. Karlsen, A table is an unordered set. There is no such thing as "position in the table", only "position in the (ordered) resultset".
LukeH
A: 

There's no way you can tell that without selecting an entire subset of records. If your PK is of integer type, you can

select count(*) from mytable 
    where id <= 10 -- Record with ID 10
    order by mycolumn asc
Anton Gogolev
That returns the position when ordered by id, the 'order by' clause has no effect.
Guffa
+2  A: 

SQL doesn't work that way. It's set-based, which means that "position in that result table" is meaningless to the database.

You can keep track of position when you map the ResultSet into a collection of objects or when you iterate over it.

duffymo
+1 excellent answer. SQL Server is *NOT* like dBase anymore - no more "record + 1" or such.
marc_s
If position is meaningless, what is ORDER BY used for? Or LIMIT, TOP, and ROW_NUMBER?
Andomar
LIMIT, TOP, and ROW_NUMBER() are not part of the standard SQL language.
Bill Karwin
I think standard SQL abstracts away the "physical row number". What the poster is asking is the position of a row in an ORDER BY sequence, which has a well-defined meaning in standard SQL.
Andomar
CREATE INDEX is not part of any SQL standard, either. Should I stop using indices because they're not ISO?
Ken
+1  A: 

You can count the number of records where the value that you are sorting on has a lower value than the record that you know the key value of:

select count(*)
from mytable
where mycolumn < (select mycolumn from mytable where key = 42)
Guffa
+1 Simple and doesn't depend on ROW_NUMBER(). Though you'd need to add 1 to the result, or chance < to <=.
Andomar
Yes, if you want the position to be one based instead of zero based.
Guffa
A: 

Unfortunately you cannot get "the position of a row in a table".

The best you can get, using ORDER BY and a variant of the ROW_NUMBER construct (depends on the database engine in use), is the position of a row in the resultset of the query executed.

This position does not map back to any position in the table, though, unless the ORDER BY is on a set of clustered index columns, but even then that position might be invalidated the next second.

What I would like to know is what you intended to use this "position" for.

Lasse V. Karlsen