How to display the record with the highest value in Oracle?

删除回忆录丶 提交于 2019-12-01 23:00:08

Sometimes ORA-00907: missing right parenthesis means exactly that: we have a left bracket without a matching right one. But it can also be thrown by a syntax error in a part of a statement bounded by parentheses.

It's that second cause here: LIMIT is a Mysql command which Oracle does not recognise. You can use an analytic function here:

SELECT A1.artistid, A1.firstname, TEMP1.avgProfit
FROM 
(
    select  artistid
            , avgProfit
            , rank() over (order by avgProfit desc) as rnk
    from (
        SELECT 
            AVG(salesPrice - AcquisitionPrice) as avgProfit, 
            W1.artistid as artistid
        FROM dtoohey.trans T1
        INNER JOIN dtoohey.WORK W1
        ON W1.workid = T1.workid
        GROUP BY artistid
    ) 
) TEMP1
INNER JOIN dtoohey.artist A1
    ON A1.artisid = TEMP1.artistid
where TEMP1.rnk = 1

This uses the RANK() function which will return more than one row if several artists achieve the same average profit. You might want to use ROW_NUMBER() instead. Analytic functions can be very powerful. Find out more.

You can apply ROWN_NUMBER(), RANK() and DENSE_RANK() to any top-n problem. You can use one of them to solve your first problem too.


"however the avg profit is null."

That's probably a data issue. If one of the numbers in (salesPrice - AcquisitionPrice) is null the result will be null, and won't be included in the average. If all the rows for an artist are null the AVG() will be null.

As it happens the sort order will put NULL last. But as the PARTITION BY clause sorts by AvgProfit desc that puts the NULL results at rank 1. The solution is to use the NULLS LAST in the windowing clause:

            , rank() over (order by avgProfit desc nulls last) as rnk

This will guarantee you a non-null result at the top (providing at least one of your artists has values in both columns).

1st question - Oracle does not guarantee the order by which rows are retrieved. Hence you must first order and then limit the ordered set. SELECT * from ( SELECT A1.* From dtoohey.artist A1 INNER JOIN ( SELECT COUNT(W1.ArtistID) AS COUNTER, artistID FROM dtoohey.trans T1 INNER JOIN dtoohey.work W1 ON W1.workid = T1.Workid GROUP BY W1.artistID ) TEMP1 ON TEMP1.artistID = A1.artistID WHERE A1.artistID = TEMP1.artistId ORDER BY COUNTER desc ) WHERE ROWNUM = 1

2nd question: I believe (haven't tested) that you have that LIMIT 1 wrong. That keyword is for use with Bulk collecting.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!