Thread: How ad an increasing index to a query result?

How ad an increasing index to a query result?

From
Josip
Date:
Hello,

Could somebody please try to help me with this problem?
So, let’s say that I have the query:

CREATE SEQUENCE c START 1;

SELECT a, nextval('c') as b
FROM table1
ORDER BY a DESC LIMIT 5;

I.e., I want to pick the 5 largest entries from table1 and show them
alongside a new index column that tells the position of the entry. For
example:

 a  | b
--------
82 | 5
79 | 4
34 | 3
12 | 2
11 | 1

However, when I try this approach, the values of column b don’t follow
the correct order. How should I go about and modify my code?

Re: How ad an increasing index to a query result?

From
Andrew Bailey
Date:
I found an article that should help you with the answer:

http://explainextended.com/2009/05/05/postgresql-row-numbers/

ROWNUM is a very useful pseudocolumn in Oracle that returns the
position of each row in a final dataset.

Upcoming PostgreSQL 8.4 will have this pseudocolumn, but as for now
will we need a hack to access it. (in 8,3)

The main idea is simple:

   1. Wrap the query results into an array
   2. Join this array with a generate_series() so that numbers from 1
to array_upper() are returned
   3. For each row returned, return this number (as ROWNUM) along the
corresponding array member (which is the row from the original query)
...

See original article for the code

Hope it helps

Andy Bailey


On Wed, Oct 14, 2009 at 12:05 PM, Josip <josip.2000@gmail.com> wrote:
> Hello,
>
> Could somebody please try to help me with this problem?
> So, let’s say that I have the query:
>
> CREATE SEQUENCE c START 1;
>
> SELECT a, nextval('c') as b
> FROM table1
> ORDER BY a DESC LIMIT 5;
>
> I.e., I want to pick the 5 largest entries from table1 and show them
> alongside a new index column that tells the position of the entry. For
> example:
>
>  a  | b
> --------
> 82 | 5
> 79 | 4
> 34 | 3
> 12 | 2
> 11 | 1
>
> However, when I try this approach, the values of column b don’t follow
> the correct order. How should I go about and modify my code?
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>



--
Andrew Bailey

(312) 866 9556

NOTA DE CONFIDENCIALIDAD Y DE NO DIVULGACIÓN:
La información contenida en este E-mail y sus archivos adjuntos es
confidencial y sólo puede ser utilizada por el individuo
o la empresa a la cual está dirigido. Si no es el receptor autorizado,
cualquier retención, difusión,
distribución o copia de este mensaje queda prohibida y sancionada por
la ley. Si por error recibe este
mensaje, favor devolverlo y borrarlo inmediatamente.

Re: How ad an increasing index to a query result?

From
"Chris Spotts"
Date:
>
> SELECT a, nextval('c') as b
> FROM table1
> ORDER BY a DESC LIMIT 5;
>
> I.e., I want to pick the 5 largest entries from table1 and show them
> alongside a new index column that tells the position of the entry. For
> example:
>
>  a  | b
> --------
> 82 | 5
> 79 | 4
> 34 | 3
> 12 | 2
> 11 | 1
>
[Spotts, Christopher]
Sounds like you you want 8.4 and windowing functions like row_number().
(http://www.postgresql.org/docs/8.4/static/functions-window.html)
If you have 8.4.


Re: How ad an increasing index to a query result?

From
LaMi
Date:
Josip wrote:
> Hello,
>
> Could somebody please try to help me with this problem?
> So, let’s say that I have the query:
>
> CREATE SEQUENCE c START 1;
>
> SELECT a, nextval('c') as b
> FROM table1
> ORDER BY a DESC LIMIT 5;
>
> I.e., I want to pick the 5 largest entries from table1 and show them
> alongside a new index column that tells the position of the entry. For
> example:
>
>  a  | b
> --------
> 82 | 5
> 79 | 4
> 34 | 3
> 12 | 2
> 11 | 1
>
> However, when I try this approach, the values of column b don’t follow
> the correct order. How should I go about and modify my code?
>
You can try using a sequence with a negative increment like below

CREATE SEQUENCE test_sequence
   INCREMENT -1
   START 100
   MINVALUE 1
   MAXVALUE 100;

- mrLami


Re: How ad an increasing index to a query result?

From
Alban Hertroys
Date:
On 14 Oct 2009, at 19:05, Josip wrote:

> Hello,
>
> Could somebody please try to help me with this problem?

> I.e., I want to pick the 5 largest entries from table1 and show them
> alongside a new index column that tells the position of the entry. For
> example:
>
> a  | b
> --------
> 82 | 5
> 79 | 4
> 34 | 3
> 12 | 2
> 11 | 1


Short of enumerating those results in your application, the easiest
approach is probably to wrap your query in a join with generate_series
like so:

SELECT a, s.b
FROM (
    SELECT a
    FROM table1
    ORDER BY a DESC LIMIT 5
) AS t1, generate_series(5, 1, -1) AS s(b)

Alban Hertroys

--
Screwing up is the best way to attach something to the ceiling.


!DSPAM:737,4adaee3411688629581426!



Re: How ad an increasing index to a query result?

From
Thom Brown
Date:
2009/10/14 Josip <josip.2000@gmail.com>:
> Hello,
>
> Could somebody please try to help me with this problem?
> So, let’s say that I have the query:
>
> CREATE SEQUENCE c START 1;
>
> SELECT a, nextval('c') as b
> FROM table1
> ORDER BY a DESC LIMIT 5;
>
> I.e., I want to pick the 5 largest entries from table1 and show them
> alongside a new index column that tells the position of the entry. For
> example:
>
>  a  | b
> --------
> 82 | 5
> 79 | 4
> 34 | 3
> 12 | 2
> 11 | 1
>
> However, when I try this approach, the values of column b don’t follow
> the correct order. How should I go about and modify my code?

The problem here is that the sequence will merely act as a counter,
and knows nothing about the data you're using it to count against.  In
the example you gave, it appears you're inserting data into the table
in ascending order, but you want it output in descending order.

If you're using PostgreSQL 8.4, you can do the following:

SELECT a, rank() OVER (ORDER BY a DESC)
FROM table1
ORDER BY a DESC

This is called a window function.  It is using a window aggregate
function to rank column a in descending order (as declared in the OVER
clause).

If you are using an earlier version of Postgres, you could always use
a temporary table:

CREATE TEMP TABLE temp_table1
(
orderseq SERIAL PRIMARY KEY,
a INTEGER NOT NULL
) ON COMMIT DROP;

INSERT INTO temp_table1 (a)
SELECT a
FROM table1
ORDER BY a DESC;

SELECT orderseq, a
FROM temp_table1;

There may be another way, but can't think of one of the top of my head.

Thom

Re: How ad an increasing index to a query result?

From
Raymond O'Donnell
Date:
On 18/10/2009 11:30, Alban Hertroys wrote:

> Short of enumerating those results in your application, the easiest
> approach is probably to wrap your query in a join with generate_series
> like so:
>
> SELECT a, s.b
> FROM (
>     SELECT a
>     FROM table1
>     ORDER BY a DESC LIMIT 5
> ) AS t1, generate_series(5, 1, -1) AS s(b)
>

Won't that just give you the cartesian product of the two sets? I tried
something similar yesterday out of curiosity, and that's what I got.

The only things I can think of are (i) as you say, enumerate the results
in the application or (ii) use a temporary sequence as someone else
suggested.

Ray.

------------------------------------------------------------------
Raymond O'Donnell, Director of Music, Galway Cathedral, Ireland
rod@iol.ie
Galway Cathedral Recitals: http://www.galwaycathedral.org/recitals
------------------------------------------------------------------

Re: How ad an increasing index to a query result?

From
Merlin Moncure
Date:
On Sun, Oct 18, 2009 at 12:00 PM, Raymond O'Donnell <rod@iol.ie> wrote:
> On 18/10/2009 11:30, Alban Hertroys wrote:
>
>> Short of enumerating those results in your application, the easiest
>> approach is probably to wrap your query in a join with generate_series
>> like so:
>>
>> SELECT a, s.b
>> FROM (
>>     SELECT a
>>     FROM table1
>>     ORDER BY a DESC LIMIT 5
>> ) AS t1, generate_series(5, 1, -1) AS s(b)
>>
>
> Won't that just give you the cartesian product of the two sets? I tried
> something similar yesterday out of curiosity, and that's what I got.
>
> The only things I can think of are (i) as you say, enumerate the results
> in the application or (ii) use a temporary sequence as someone else
> suggested.

yeah, the above gives a cartesian product.  Row number is really the
way to go here.  Using pre window tactics, it looks like we need:

select a, b from
(
  select a, nextval('c')  as b from
  (
    SELECT a,
    FROM table1
    ORDER BY a DESC LIMIT 5
  ) q order by a
) q order by a desc;

aside: it's never a good idea to write queries like this:
select func(), foo from bar order by foo limit x;
if you are concerned about how many times foo executes.  This is a
huge gotcha that constantly comes up on the lists.  see the warning
here:

http://www.postgresql.org/docs/8.3/interactive/explicit-locking.html#ADVISORY-LOCKS

merlin