This is my current query. I used an inline view to only show the top 5 results for the companies with the highest volume of shares traded at a specific stock exchange. Alongside this, I want to show the most recent price for each row. This information is found in the stock_price table with a respective date.
SELECT
*
FROM
(
SELECT
c.name AS company_name,
t.stock_id AS stock_id,
SUM(t.shares) AS Trade_Volume
FROM company c
JOIN trade t
ON c.stock_id = t.stock_id
JOIN stock_price sp
ON sp.stock_ex_id =3
AND sp.stock_id = t.stock_id
WHERE t.stock_ex_id = 3
GROUP BY
c.name, t.stock_id
ORDER BY SUM(t.shares) DESC
)
WHERE
ROWNUM <= 5;
My attempt:
SELECT
c.name,
SUM(t.shares),
sp.price
FROM
company c
JOIN trade t
ON c.stock_id = t.stock_id
JOIN stock_price sp
ON sp.stock_id = t.stock_id
AND sp.stock_ex_id = t.stock_ex_id
WHERE sp.stock_ex_id =3
GROUP BY c.name, sp.price
;
The output:
You could do something like this (not tested; explained after the query):
with
high_vols as (
select *
from (
select c.name as company_name, c.stock_id as stock_id,
sum(t.shares) as trade_volume
from company c join trade t on c.stock_id = t.stock_id
where t.stock_ex_id = 3
group by c_name, c.stock_id
order by sum(t.shares) desc
)
where rownum <= 5
)
, last_prices as (
select stock_id,
min(price) keep (dense_rank last order by price_date) as last_price
from stock_price
where stock_id in (select stock_id from high_vols) and stock_ex_id = 3
group by stock_id
)
select hv.company_name, hv.stock_id, hv.total_volume, lp.last_price
from high_vols hv join last_prices lp on hv.stock_id = lp.stock_id
order by total_volume desc
;
HIGH_VOLS
is the query you have already. It finds the five stocks with the highest volume on a given exchange - and on a given date if you will add that in the query; you didn't do that in your query, and you didn't describe your data in enough detail to attempt to add that in the query, but you should be able to do that yourself. Note that the same observation (about date) applies to the second query in the WITH
clause.
LAST_PRICES
selects prices from the price table, filtered for the exchange, for the five stocks that were found in the first subquery, and for the desired date (after you add that in). It uses the aggregate LAST function - a very useful aggregate function for this kind of query, unfortunately ignored by many developers.
The last step is to join the two tables. It is best to join the tables only after the two aggregations. (In any case, if statistics are up-to-date, the optimizer will find the best order of operations regardless of how you write the query, as long as it is written correctly. In fact, the optimizer will probably choose to do the "top-five" aggregation just on the "trades" table, and join to "company" only at the very last step.)