Thread: help with query: advanced ORDER BY...

help with query: advanced ORDER BY...

From
Date:
hi list

here's what i would like to do:

table1:
field0: id
field1: boolean
field2: numeric
field3: varchar

when selecting records from this table, i would like to have different sort
orders depending if field1 is true or false: all records with field1 = true
should be sorted with field2 first then field3, all records having field2 =
false sorted by field3 first then field2.

example:

field0  |  field1 |  field 2 |  field3
-------------------------------------------
1            t           2           b
2            f           1           z
3            t           1           a
4            f            4           a


desired output after sorting
4            f            4           a
2            f           1           z
3            t           1           a
1            t           2           b

is this possible in a single query?

(i hope my explanations make sense ;-))

- thomas



Re: help with query: advanced ORDER BY...

From
Michael Fuhr
Date:
On Sat, Jan 14, 2006 at 05:47:41PM +0100, me@alternize.com wrote:
> when selecting records from this table, i would like to have different sort
> orders depending if field1 is true or false: all records with field1 = true
> should be sorted with field2 first then field3, all records having field2 =
> false sorted by field3 first then field2.

Something like this might work:

SELECT * FROM table1
ORDER BY field1,
         CASE WHEN field1 THEN field2 ELSE NULL END,
         CASE WHEN field1 THEN field3 ELSE NULL END,
         CASE WHEN field1 THEN NULL ELSE field3 END,
         CASE WHEN field1 THEN NULL ELSE field2 END;

If field2 and field3 were the same type then you could shorten the
query to:

SELECT * FROM table1
ORDER BY field1,
         CASE WHEN field1 THEN field2 ELSE field3 END,
         CASE WHEN field1 THEN field3 ELSE field2 END;

The extra CASE statements in the first form are necessary if field2
and field3 are different types; with the shorter version you'd get
an error like:

ERROR:  CASE types character varying and numeric cannot be matched

--
Michael Fuhr

Re: help with query: advanced ORDER BY...

From
Date:
> Something like this might work:
>
> SELECT * FROM table1
> ORDER BY field1,
>         CASE WHEN field1 THEN field2 ELSE NULL END,
>         CASE WHEN field1 THEN field3 ELSE NULL END,
>         CASE WHEN field1 THEN NULL ELSE field3 END,
>         CASE WHEN field1 THEN NULL ELSE field2 END;


it indeed does, thanks alot. will pgsql still use the indices when ordering
through CASE?

cheers,
thomas



Re: help with query: advanced ORDER BY...

From
Michael Fuhr
Date:
On Sat, Jan 14, 2006 at 09:32:03PM +0100, me@alternize.com wrote:
> >Something like this might work:
> >
> >SELECT * FROM table1
> >ORDER BY field1,
> >        CASE WHEN field1 THEN field2 ELSE NULL END,
> >        CASE WHEN field1 THEN field3 ELSE NULL END,
> >        CASE WHEN field1 THEN NULL ELSE field3 END,
> >        CASE WHEN field1 THEN NULL ELSE field2 END;
>
>
> it indeed does, thanks alot. will pgsql still use the indices when ordering
> through CASE?

I don't think so, unless you define a multicolumn index on those
specific expressions.

Why the different ordering?  What are you doing?

--
Michael Fuhr

Re: help with query: advanced ORDER BY...

From
Date:
> I don't think so, unless you define a multicolumn index on those
> specific expressions.
>
> Why the different ordering?  What are you doing?

here's what we currently need it for (simplified):

the movie schedules for theatres normally contains the information
theater_id, screen_date, screen_time, screen_number, movie_name and should
be outputed accordingly. it now happens to have some cinema multiplex owners
who for some reasons do not want to publish the screen_number to the
public - but the internal data we receive does contain that information.

thus, for all mulitplex theatres that do not want to publish screen number
information, the data must be ordered by theater_id, screen_date,
screen_time, movie_name.

SELECT * FROM schedule
ORDER BY theater_id,
    screen_date,
    screen_time,
    CASE WHEN no_screennumber THEN NULL ELSE screen_number END,
    movie_name;

the (simplyified) query does that just fine... here the loss of indexing
doesn't matter that much as the screen numbers are only in a small range and
thus a seqscan probably as fast as an indexscan.

but there are other more complex queries needing the similar logic with
multiple fields involved, that probably might suffer some performance loss.
i haven't touched the more complex ones yet, but still was wondering if
there might be some performance problems - the realtime queries take quite
long already due to some other non-optimized tables so i wouldn't want to
make this even worse before i had a chance to optimize them ;-)

cheers,
thomas



Re: help with query: advanced ORDER BY...

From
Michael Glaesemann
Date:
On Jan 15, 2006, at 11:15 , <me@alternize.com> <me@alternize.com> wrote:

> the movie schedules for theatres normally contains the information
> theater_id, screen_date, screen_time, screen_number, movie_name and
> should be outputed accordingly. it now happens to have some cinema
> multiplex owners who for some reasons do not want to publish the
> screen_number to the public - but the internal data we receive does
> contain that information.

Something you may consider doing is creating a view that masks the
screen_number in those cases, something like

create view schedule_public_view as
select theater_id
    , screen_date
    , screen_time
    , case when no_screen_number then 0 else screen_number  end as
screen_number
    , movie_name
from schedules;

Michael Glaesemann
grzm myrealbox com




Re: help with query: advanced ORDER BY...

From
Date:
> Something you may consider doing is creating a view that masks the
> screen_number in those cases, something like
>
> create view schedule_public_view as
> select theater_id
> , screen_date
> , screen_time
> , case when no_screen_number then 0 else screen_number  end as
> screen_number
> , movie_name
> from schedules;

wouldn't this be the same problem: pgsql not using the index for
screen_number anymore?

- thomas



Re: help with query: advanced ORDER BY...

From
Michael Glaesemann
Date:
On Jan 15, 2006, at 19:53 , <me@alternize.com> <me@alternize.com> wrote:

>> Something you may consider doing is creating a view that masks the
>> screen_number in those cases, something like
>>
>> create view schedule_public_view as
>> select theater_id
>> , screen_date
>> , screen_time
>> , case when no_screen_number then 0 else screen_number  end as
>> screen_number
>> , movie_name
>> from schedules;
>
> wouldn't this be the same problem: pgsql not using the index for
> screen_number anymore?

That may be. Only way to be sure is to try it. (And I'm not
knowledgeable enough to know for sure.)

Michael Glaesemann
grzm myrealbox com




Re: help with query: advanced ORDER BY...

From
Stephan Szabo
Date:
On Sun, 15 Jan 2006 me@alternize.com wrote:

> > Something you may consider doing is creating a view that masks the
> > screen_number in those cases, something like
> >
> > create view schedule_public_view as
> > select theater_id
> > , screen_date
> > , screen_time
> > , case when no_screen_number then 0 else screen_number  end as
> > screen_number
> > , movie_name
> > from schedules;
>
> wouldn't this be the same problem: pgsql not using the index for
> screen_number anymore?

Theoretically an expressional index with the case expression should be
usable for sorting with more complicated expressions like that. That
really only an option if theres a small number of fixed orders though (and
in testing it looked like you might need to play with settings to get it
chosen).