Re: Need help with complicated SQL statement - Mailing list pgsql-general

From Shane Ambler
Subject Re: Need help with complicated SQL statement
Date
Msg-id 473F18AF.2090706@Sheeky.Biz
Whole thread Raw
In response to Need help with complicated SQL statement  (Ted Byers <r.ted.byers@rogers.com>)
Responses Re: Need help with complicated SQL statement  (Ted Byers <r.ted.byers@rogers.com>)
List pgsql-general
Ted Byers wrote:
> Please consider the following statement (it becomes
> obvious if you remember the important thing about the
> table is that it has columns for each of stock_id,
> price_date, and price).
>
> (SELECT * FROM stockprices WHERE stock_id = 1 ORDER BY
> price_date DESC LIMIT 1)
> UNION
> (SELECT * FROM (SELECT * FROM stockprices WHERE
> stock_id = 1 ORDER BY price_date DESC LIMIT 22) AS T2
> ORDER BY T2.price_date ASC LIMIT 1)
> UNION
> (SELECT * FROM (SELECT * FROM stockprices WHERE
> stock_id = 1 ORDER BY price_date DESC LIMIT 66) AS T3
> ORDER BY T3.price_date ASC LIMIT 1)
> UNION
> (SELECT * FROM (SELECT * FROM stockprices WHERE
> stock_id = 1 ORDER BY price_date DESC LIMIT 132) AS T4
> ORDER BY T4.price_date ASC LIMIT 1)
> UNION
> (SELECT * FROM (SELECT * FROM stockprices WHERE
> stock_id = 1 ORDER BY price_date DESC LIMIT 264) AS T5
> ORDER BY T5.price_date ASC LIMIT 1);
>
> This statement works flawlessly, and is blindingly
> fast relative to everything else I have tried.  But I
> am stuck.

I would have these subselects as -

UNION
(SELECT * FROM stockprices WHERE
  stock_id = 1 ORDER BY price_date DESC LIMIT 1 OFFSET 264)

I would expect that to give the same result but make the query plan a
bit simpler and quicker using less memory.

> First, while this statement gets me the correct data,
> I need to obtain a single record with stock_id,
> current price (that obtained from the first select
> statement in the union, and each of the prices
> returned by the subsequent select statements as a the
> current price minus the price at the previous date,
> and the result divided by the price at the previous
> date, expressed as a percentage.  I do not yet know
> how to do this using SQL (it would be trivial if I
> exported the data to Java or C++ - but it isn't clear
> how to do it within SQL).

I haven't tested this but I would start with -

CREATE VIEW stock_price_combined AS
SELECT
stock_id

, (SELECT stock_price FROM stockprices WHERE stock_id = OT.stock_id
ORDER BY price_date DESC LIMIT 1) as orig_price

, (SELECT stock_price FROM stockprices WHERE stock_id = OT.stock_id
ORDER BY price_date DESC LIMIT 1 OFFSET 22) as price_two

, (SELECT stock_price FROM stockprices WHERE stock_id = OT.stock_id
ORDER BY price_date DESC LIMIT 1 OFFSET 66) as price_three

, (SELECT stock_price FROM stockprices WHERE stock_id = OT.stock_id
ORDER BY price_date DESC LIMIT 1 OFFSET 132) as price_four

, (SELECT stock_price FROM stockprices WHERE stock_id = OT.stock_id
ORDER BY price_date DESC LIMIT 1 OFFSET 264) as price_five

FROM stock_prices OT;


Then you can -

SELECT
orig_price
, (orig_price - price_two) as price_increase
, ((orig_price - price_two)/price_two) as percentile
...
...

FROM stock_price_combined

WHERE stock_id in (SELECT stock_id FROM someTable WHERE ...)


> To make things more difficult, suppose I have another
> select statement that returns a set of stock_ids.  How
> do I apply the SQL logic I require to only those
> stocks in the set returned by a statement like SELECT
> stock_id FROM someTable WHERE ...  The result of this
> extension would be that I have one record for each
> stock in the selected set of stocks.

SELECT * from stockprices WHERE stock_id in (SELECT stock_id FROM
someTable WHERE ...)



If that isn't the answer you want I hope it points you in the right
direction...


--

Shane Ambler
pgSQL@Sheeky.Biz

Get Sheeky @ http://Sheeky.Biz

pgsql-general by date:

Previous
From: Tom Lane
Date:
Subject: Re: pg_dump not including custom CAST?
Next
From: "nabakumar salam"
Date:
Subject: HINT: Please REINDEX it.