Thread: SQL Newbie

SQL Newbie

From
"Lane Van Ingen"
Date:
It seems to me that I should be able to do this, but after 5 hrs of trying,
I
can't figure this one out.

I could do this in two queries, but seems like I should be able to do this
in
one. What I am trying to do:Find the highest speed at which each interface of a router has run over
time.

I have three tables, two of which (interface, speed_history) are being used
in
this query (primary / foreign key fields noted as PK / FK):
 router    -> 1:M -> interface         -> 1:M -> speed_history ------------------- ---------------------------
--------------------------
- router_no (int2) PK interface_id (int4) PK      interface_id (int4) PK name (varchar)      router_no (int2) FK
updated_time (timestamp)
 
PK                     link_description (varchar)  speed        (int4)

Data in speed history looks like this:   interface_id  updated_time          speed   1             2005-08-11 08:10:23
450112   1             2005-08-11 10:53:34   501120 <---   1             2005-08-11 10:58:11   450112   2
2005-08-1108:10:23   450112 <---   2             2005-08-11 11:00:44   350234   3             2005-08-11 08:10:23
450112<---
 
The rows of speed_history I want back are marked above with ' <--- '.

Query results should look like:    interface.interface_id    interface.link_description    speed_history.updated_time
speed_history.speed
 




Re: SQL Newbie

From
Sean Davis
Date:
On 8/12/05 11:09 AM, "Lane Van Ingen" <lvaningen@esncc.com> wrote:

> It seems to me that I should be able to do this, but after 5 hrs of trying,
> I
> can't figure this one out.
> 
> I could do this in two queries, but seems like I should be able to do this
> in
> one. What I am trying to do:
> Find the highest speed at which each interface of a router has run over
> time.
> 
> I have three tables, two of which (interface, speed_history) are being used
> in
> this query (primary / foreign key fields noted as PK / FK):
> 
> router    -> 1:M -> interface         -> 1:M -> speed_history
> ------------------- --------------------------- --------------------------
> -
> router_no (int2) PK interface_id (int4) PK      interface_id (int4) PK
> name (varchar)      router_no (int2) FK         updated_time (timestamp)
> PK
>                     link_description (varchar)  speed        (int4)
> 
> Data in speed history looks like this:
>   interface_id  updated_time          speed
>   1             2005-08-11 08:10:23   450112
>   1             2005-08-11 10:53:34   501120 <---
>   1             2005-08-11 10:58:11   450112
>   2             2005-08-11 08:10:23   450112 <---
>   2             2005-08-11 11:00:44   350234
>   3             2005-08-11 08:10:23   450112 <---
> The rows of speed_history I want back are marked above with ' <--- '.
> 
> Query results should look like:
>    interface.interface_id
>    interface.link_description
>    speed_history.updated_time
>    speed_history.speed

What about (untested):

SELECT a.interface_id,      a.link_description,      c.updated_time,      c.speed
FROM      interface a,      (select interface_id,max(speed) as speed       from speed_history,interface group by
interface_id)as b,      speed_history c
 
WHERE      b.interface_id=a.interface_id AND      c.speed=b.speed;

Sean



Re: SQL Newbie

From
"Nick Stone"
Date:
Hope this helps

SELECT*
FROMspeed_history as outside etc..
WHERE(speed = (    SELECT        speed    FROM        speed_history as inside etc..    WHERE        (outside.interface
=inside.interface)    LIMIT 1    ORDER BY        speed DESC    ))
 

Hopefully you get the idea - basically it's a corelated sub-query - very
useful

Nick

-----Original Message-----
From: pgsql-sql-owner@postgresql.org [mailto:pgsql-sql-owner@postgresql.org]
On Behalf Of Lane Van Ingen
Sent: 12 August 2005 16:09
To: pgsql-sql@postgresql.org
Subject: [SQL] SQL Newbie

It seems to me that I should be able to do this, but after 5 hrs of trying,
I can't figure this one out.

I could do this in two queries, but seems like I should be able to do this
in one. What I am trying to do:Find the highest speed at which each interface of a router has run over
time.

I have three tables, two of which (interface, speed_history) are being used
in this query (primary / foreign key fields noted as PK / FK):
 router    -> 1:M -> interface         -> 1:M -> speed_history ------------------- ---------------------------
--------------------------
- router_no (int2) PK interface_id (int4) PK      interface_id (int4) PK name (varchar)      router_no (int2) FK
updated_time (timestamp)
 
PK                     link_description (varchar)  speed        (int4)

Data in speed history looks like this:   interface_id  updated_time          speed   1             2005-08-11 08:10:23
450112   1             2005-08-11 10:53:34   501120 <---   1             2005-08-11 10:58:11   450112   2
2005-08-1108:10:23   450112 <---   2             2005-08-11 11:00:44   350234   3             2005-08-11 08:10:23
450112<---
 
The rows of speed_history I want back are marked above with ' <--- '.

Query results should look like:    interface.interface_id    interface.link_description    speed_history.updated_time
speed_history.speed
 



---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster





Re: SQL Newbie

From
Bruno Wolff III
Date:
> Data in speed history looks like this:
>     interface_id  updated_time          speed
>     1             2005-08-11 08:10:23   450112
>     1             2005-08-11 10:53:34   501120 <---
>     1             2005-08-11 10:58:11   450112
>     2             2005-08-11 08:10:23   450112 <---
>     2             2005-08-11 11:00:44   350234
>     3             2005-08-11 08:10:23   450112 <---
> The rows of speed_history I want back are marked above with ' <--- '.
> 
> Query results should look like:
>      interface.interface_id
>      interface.link_description
>      speed_history.updated_time
>      speed_history.speed

The main idea is to join a select of max speeds grouped by interface_id
to the interface table.

If the query runs too slow, then you may get better performance having an
index on (interface_id, speed) and using subselects. In this case
you want to select information about all of interfaces and then have
one of the columns be a subselect that selects one (using limit) speed
from rows that have a matching interface_id ordered by interface_id desc,
speed desc. This combination of limit and order by will be faster than
using max.


Re: SQL Newbie

From
"Owen Jacobson"
Date:
Nick Stone wrote:

> Hope this helps
>
> SELECT
>     *
> FROM
>     speed_history as outside etc..
> WHERE
>     (speed = (
>         SELECT
>             speed
>         FROM
>             speed_history as inside etc..
>         WHERE
>             (outside.interface = inside.interface)
>         LIMIT 1
>         ORDER BY
>             speed DESC
>         )
>     )

Worth noting that ORDER BY speed DESC LIMIT 1 is fundamentally the same as
MAX (speed), except that MAX (speed) doesn't take advantage of any index
present.  This is a fairly common idiom but a self-described SQL Newbie may
not see the equivalence instantly.

-Owen



Re: SQL Newbie

From
Bruno Wolff III
Date:
On Fri, Aug 12, 2005 at 18:57:34 +0100, Nick Stone <nick@harelane.com> wrote:
> Hope this helps
> 
> SELECT
>     *
> FROM
>     speed_history as outside etc..
> WHERE
>     (speed = (
>         SELECT
>             speed
>         FROM
>             speed_history as inside etc..
>         WHERE
>             (outside.interface = inside.interface)
>         LIMIT 1
>         ORDER BY
>             speed DESC
>         )
>     )
> 
> Hopefully you get the idea - basically it's a corelated sub-query - very
> useful
> 

Note that you want to order by interface DESC, speed DESC in the subselect
and have an index on (interface, speed) for this to really be efficient.
I think 8.1 might be smart enough to use an index on (interface, speed)
in the above case, but currently released versions won't.