Обсуждение: Select first ten of each category?

Поиск
Список
Период
Сортировка

Select first ten of each category?

От
Benjamin Smith
Дата:
I'm stumped on this one...

I have a table defined thusly:

create table items (
id serial,
category integer not null references category(id),
name varchar not null,
price real,
unique(category, name));

It has a LARGE number of entries. I'd like to grab the 10 most expensive items
from each category in a single query. How can this be done? Something like

Select items.*
FROM items
where id IN (
    select firstTen(id) FROM items
    group by category
    ORDER BY price DESC
    )
ORDER BY price desc;

But I've not found any incantation to make this idea work...

-Ben
--
"The best way to predict the future is to invent it."
- XEROX PARC slogan, circa 1978

Re: Select first ten of each category?

От
Yanni Chiu
Дата:
Benjamin Smith wrote:
> It has a LARGE number of entries. I'd like to grab the 10 most expensive items
> from each category in a single query. How can this be done?

Use a LIMIT on your SELECT. See:
http://www.postgresql.org/docs/8.1/static/queries-limit.html

Re: Select first ten of each category?

От
Michael Glaesemann
Дата:
On Apr 13, 2006, at 10:16 , Benjamin Smith wrote:

> I'm stumped on this one...
>
> I have a table defined thusly:
>
> create table items (
> id serial,
> category integer not null references category(id),
> name varchar not null,
> price real,
> unique(category, name));
>
> It has a LARGE number of entries. I'd like to grab the 10 most
> expensive items
> from each category in a single query. How can this be done?

You can use a correlated subquery, something like (untested):

select category, id, name, price
     , (
         select count(*)
         from items i2
         where i2.category = i.category
             and i2.price > i.price
         ) + 1 as rank
from items i
order by category, rank desc;

Note that this query actually counts the number of items (in the
category) with prices greater than the given item's price.

And to limit it just to the top 10 items:

select category, id, name, price, rank
from (
     select category, id, name, price
         , (
             select count(*)
             from items i2
             where i2.category = i.category
                 and i2.price > i.price
             ) + 1 as rank
     from items i
)
where rank <= 10
order by category, rank desc;

Note that this may return more than 10 items per category in the case
of more than one item in a given category having the same price.

Hope this points you in the right direction.

Michael Glaesemann
grzm myrealbox com




Re: Select first ten of each category?

От
Michael Glaesemann
Дата:
On Apr 13, 2006, at 11:08 , Yanni Chiu wrote:

> Benjamin Smith wrote:
>> It has a LARGE number of entries. I'd like to grab the 10 most
>> expensive items from each category in a single query. How can this
>> be done?
>
> Use a LIMIT on your SELECT. See:
> http://www.postgresql.org/docs/8.1/static/queries-limit.html

Without using UNION, (which would require writing a select statement
for each category), how would LIMIT allow him to do this for each
category in a single query?


Michael Glaesemann
grzm myrealbox com




Re: Select first ten of each category?

От
Yanni Chiu
Дата:
Michael Glaesemann wrote:
> Without using UNION, (which would require writing a select statement
> for each category), how would LIMIT allow him to do this for each
> category in a single query?

You're right, it would need a UNION, and a SELECT per category.
So there'd be another SELECT to find all the categories beforehand.

Re: Select first ten of each category?

От
Brent Wood
Дата:

On Wed, 12 Apr 2006, Benjamin Smith wrote:

> I'm stumped on this one...
>
> I have a table defined thusly:
>
> create table items (
> id serial,
> category integer not null references category(id),
> name varchar not null,
> price real,
> unique(category, name));



I think this should work....

select * from items
order by price desc
limit 10;


Cheers,

  Brent Wood

>
> It has a LARGE number of entries. I'd like to grab the 10 most expensive items
> from each category in a single query. How can this be done? Something like
>
> Select items.*
> FROM items
> where id IN (
>     select firstTen(id) FROM items
>     group by category
>     ORDER BY price DESC
>     )
> ORDER BY price desc;
>
> But I've not found any incantation to make this idea work...
>

Re: Select first ten of each category?

От
"Dawid Kuroczko"
Дата:
On 4/13/06, Benjamin Smith <lists@benjamindsmith.com> wrote:
I'm stumped on this one...

I have a table defined thusly:

create table items (
id serial,
category integer not null references category(id),
name varchar not null,
price real,
unique(category, name));

It has a LARGE number of entries. I'd like to grab the 10 most expensive items
from each category in a single query. How can this be done? Something like

Select items.*
FROM items
where id IN (
        select firstTen(id) FROM items
        group by category
        ORDER BY price DESC
        )
ORDER BY price desc;

But I've not found any incantation to make this idea work...

I came up with something like this:

SELECT i.* FROM items i JOIN (
    SELECT category, (
        SELECT price FROM items ii
            WHERE ii.category=io.category
            ORDER BY price DESC OFFSET 9 LIMIT 1
        ) AS date FROM items io GROUP BY category) AS sel
    ON (i.category=sel.category AND i.price >= sel.price);

I,e.  First do a select which will return ninth price of each
category (two inner selects) and then JOIN it with a whole
table, where category and price match they way you want.

Keep in mind, if you happen to have same prices at position
near 10th, you'll end up having more than 10 returns per
given category.  Either filter it at application level, or embed
some additional key inside the join condition (like
ON (i.category=sel.category AND (i.price > sel.price OR
(i.price=sel.price AND i.id=sel.last_id)));

  Regards,
        Dawid