Solved

Converting SQL server query to Oracle 10g - using Oracle SQL developer

Posted on 2013-02-06
13
405 Views
Last Modified: 2013-02-07
The query below  gives me topprofitted salesperson.

 how can I modify it  using Rank function  or dense_rank function to get the second most profited employee. (that could be the one that with second positive profit or negative profit).

select * from
(select * from
(SELECT   s.empid employeeid, s.ename employeename, to_char(SUM(i.price * oi.qty) - s.salary,'$99,999.99') profit
    FROM salespersons s
         LEFT JOIN orders o ON s.empid = o.empid
         LEFT JOIN orderitems oi ON o.orderid = oi.orderid
         LEFT JOIN inventory i ON oi.partid = i.partid
GROUP BY s.empid, s.ename, s.salary )
order by profit )
where rownum=1 AND PROFIT IS NOT NULL;
0
Comment
Question by:ocdc
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 4
13 Comments
 
LVL 74

Expert Comment

by:sdstuber
ID: 38862078
two variations

note, I've removed the TO_CHAR from the inner query as that will cause erroneous results


SELECT *
  FROM (SELECT *
          FROM (SELECT *
                  FROM (SELECT s.empid employeeid,
                               s.ename employeename,
                               SUM(i.price * oi.qty) - s.salary profit
                          FROM salespersons s
                               LEFT JOIN orders o ON s.empid = o.empid
                               LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                               LEFT JOIN inventory i ON oi.partid = i.partid
                        GROUP BY s.empid, s.ename, s.salary)
                ORDER BY profit DESC)
         WHERE ROWNUM <= 2
        ORDER BY profit ASC)
 WHERE ROWNUM = 1;


SELECT employeeid, employeename, profit
  FROM (SELECT x.*, RANK() OVER (ORDER BY profit DESC) r
          FROM (SELECT s.empid employeeid,
                       s.ename employeename,
                       SUM(i.price * oi.qty) - s.salary profit
                  FROM salespersons s
                       LEFT JOIN orders o ON s.empid = o.empid
                       LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                       LEFT JOIN inventory i ON oi.partid = i.partid
                GROUP BY s.empid, s.ename, s.salary) x)
 WHERE r = 2
0
 
LVL 74

Expert Comment

by:sdstuber
ID: 38862080
if you want to format your profit as a string,  do that as the last step in the outermost query

for example:

select employeeid, employeename,to_char(profit,'$99,999.99') profit
FROM (SELECT x.*, RANK() OVER (ORDER BY profit DESC) r
          FROM (SELECT s.empid employeeid,
                       s.ename employeename,
                       SUM(i.price * oi.qty) - s.salary profit
                  FROM salespersons s
                       LEFT JOIN orders o ON s.empid = o.empid
                       LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                       LEFT JOIN inventory i ON oi.partid = i.partid
                GROUP BY s.empid, s.ename, s.salary) x)
 WHERE r = 2
0
 

Author Comment

by:ocdc
ID: 38862188
this one is correct. gives the correct topprofited employee.  Ho can i format SUM(i.price * oi.qty) - s.salary profit    as  ,to_char(profit,'$99,999.99') in the query below.

SELECT *
  FROM (SELECT *
          FROM (SELECT *
                  FROM (SELECT s.empid employeeid,
                               s.ename employeename,
                               SUM(i.price * oi.qty) - s.salary profit
                          FROM salespersons s
                               LEFT JOIN orders o ON s.empid = o.empid
                               LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                               LEFT JOIN inventory i ON oi.partid = i.partid
                        GROUP BY s.empid, s.ename, s.salary)
                ORDER BY profit DESC)
         WHERE ROWNUM <= 2
        ORDER BY profit ASC)
 WHERE ROWNUM = 1;
-------------------------------------------------------------------------------------
also, the query below to get the second most profitted salesperson is not giving the correct result.   It is still giving the topprofited salesperson. Same result as the one above query.

select employeeid, employeename,to_char(profit,'$99,999.99') profit
FROM (SELECT x.*, RANK() OVER (ORDER BY profit DESC) r
          FROM (SELECT s.empid employeeid,
                       s.ename employeename,
                       SUM(i.price * oi.qty) - s.salary profit
                  FROM salespersons s
                       LEFT JOIN orders o ON s.empid = o.empid
                       LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                       LEFT JOIN inventory i ON oi.partid = i.partid
                GROUP BY s.empid, s.ename, s.salary) x)
 WHERE r = 2
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 74

Expert Comment

by:sdstuber
ID: 38862200
if r=2 does not produce the 2nd result.

please post the results of...

SELECT *
  FROM (SELECT s.empid employeeid, s.ename employeename, SUM(i.price * oi.qty) - s.salary profit
          FROM salespersons s
               LEFT JOIN orders o ON s.empid = o.empid
               LEFT JOIN orderitems oi ON o.orderid = oi.orderid
               LEFT JOIN inventory i ON oi.partid = i.partid
        GROUP BY s.empid, s.ename, s.salary)
ORDER BY profit DESC


if that's too much, post the first 3 rows returned


to format the results, use the same syntax I have above...

select employeeid, employeename,to_char(profit,'$99,999.99') profit
0
 
LVL 48

Expert Comment

by:PortletPaul
ID: 38862260
my only contribution would be to include NVLs in the calculation
[& I can't see why sdstuber's would fail with r=2, so could try "< some_number"]
SELECT y.employeeid, y.employeename,TO_CHAR(y.profit,'$99,999.99') profit
FROM ( SELECT x.*, RANK() OVER (ORDER BY profit DESC) r
       FROM ( SELECT s.empid employeeid
                   , s.ename employeename
                   , SUM(NVL(i.price,0) * NVL(oi.qty,0)) - NVL(s.salary,0) profit
              FROM salespersons s
                 LEFT JOIN orders o      ON s.empid = o.empid
                 LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                 LEFT JOIN inventory i   ON oi.partid = i.partid
              GROUP BY s.empid
                     , s.ename
                     , s.salary
            ) x
     ) y
WHERE y.r < 3

Open in new window

0
 

Author Comment

by:ocdc
ID: 38862406
the the results of the query below is attached.

SELECT *
  FROM (SELECT s.empid employeeid, s.ename employeename, SUM(i.price * oi.qty) - s.salary profit
          FROM salespersons s
               LEFT JOIN orders o ON s.empid = o.empid
               LEFT JOIN orderitems oi ON o.orderid = oi.orderid
               LEFT JOIN inventory i ON oi.partid = i.partid
        GROUP BY s.empid, s.ename, s.salary)
ORDER BY profit DESC
sample-data.doc
0
 
LVL 48

Accepted Solution

by:
PortletPaul earned 500 total points
ID: 38862525
Thanks, I do suggest you try the NVLs in the query - your current results may be affected by nulls.

Otherwise include "AND PROFIT IS NOT NULL" in your selection (I prefer the NVLs because you are aggregating).

alternative 3 [sdstuber's with a tweak]:
select employeeid, employeename,to_char(profit,'$99,999.99') profit
FROM (SELECT x.*, RANK() OVER (ORDER BY NVL(profit,0) DESC) r /* tweak here */
          FROM (SELECT s.empid employeeid,
                       s.ename employeename,
                       SUM(i.price * oi.qty) - s.salary profit
                  FROM salespersons s
                       LEFT JOIN orders o ON s.empid = o.empid
                       LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                       LEFT JOIN inventory i ON oi.partid = i.partid
                GROUP BY s.empid, s.ename, s.salary) x)
 WHERE r = 2

Open in new window

0
 

Author Comment

by:ocdc
ID: 38862703
this is what I did and both work.   to get topprofit ----   Feed back is welcomed?

SELECT *
  FROM (SELECT *
          FROM (SELECT *
                  FROM (SELECT s.empid employeeid,
                               s.ename employeename,
                               SUM(i.price * oi.qty) - s.salary Topprofit
                               FROM salespersons s
                               LEFT JOIN orders o ON s.empid = o.empid
                               LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                               LEFT JOIN inventory i ON oi.partid = i.partid
                        GROUP BY s.empid, s.ename, s.salary)
                ORDER BY Topprofit DESC)
         WHERE ROWNUM <= 2
        ORDER BY Topprofit ASC)
 WHERE ROWNUM = 1;




to get second topprofit.
 ------------------------------------------------------------------
 
 SELECT employeeid, employeename, Second_Topprofit
  FROM (SELECT s.empid AS  Employeeid,
               s.ename  AS Employeename,
               TO_CHAR(SUM((i.price) * (oi.qty)) OVER (PARTITION BY s.empid) - (s.salary),
                   '$99,999.99'
               )
                   AS Second_Topprofit,
               ROW_NUMBER() OVER (ORDER BY s.salary ASC) rn
          FROM SALESPERSONS s
               LEFT JOIN ORDERS o ON s.empid = o.empid
               LEFT JOIN ORDERITEMS oi ON o.orderid = oi.orderid
               LEFT JOIN INVENTORY i ON oi.partid = i.partid)
 WHERE rn = 1 ;
0
 
LVL 74

Expert Comment

by:sdstuber
ID: 38862809
what is your question?

the first one appears to be what I posted except you changed the column name
that returns the employe with the 2nd highest value for

  SUM(i.price * oi.qty) - s.salary

your second one returns the employee with the lowest salary  the profit is not a factor
0
 

Author Comment

by:ocdc
ID: 38862819
Ok. Now that got the topprofited salesperson.  How can I give a raise to that salsperson using an update query?  Basically, I need to increase the value of the SLAESPERSONS.salary column by 12%

SELECT *
  FROM (SELECT *
          FROM (SELECT *
                  FROM (SELECT s.empid employeeid,
                               s.ename employeename,
                               SUM(i.price * oi.qty) - s.salary Topprofit
                               FROM salespersons s
                               LEFT JOIN orders o ON s.empid = o.empid
                               LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                               LEFT JOIN inventory i ON oi.partid = i.partid
                        GROUP BY s.empid, s.ename, s.salary)
                ORDER BY Topprofit DESC)
         WHERE ROWNUM <= 2
        ORDER BY Topprofit ASC)
 WHERE ROWNUM = 1;
0
 
LVL 48

Expert Comment

by:PortletPaul
ID: 38862824
I still think you are, or could be, affected by nulls.

Your "second place" query rownumber is based on only salary (I think) and seems to be by luck it gives you get the wanted result (??, well perhaps I'm not understanding)

still think sdstuber's, with null tweaks, will meet the need
SELECT
     y.employeeid
   , y.employeename
   , y.TO_CHAR(profit,'$99,999.99') as profit
   , case
        when y.r = 1 then 'Top'
        when y.r = 2 then 'Second'
        else null
      end as ranking_lbl
   , y.r as ranking_num
FROM (
       SELECT x.*
          , RANK() OVER (ORDER BY NVL(profit,0) DESC) r  /* avoid null tweak here */
       FROM (
              SELECT
                   s.empid employeeid
                 , s.ename employeename
                 , SUM(i.price * oi.qty) - s.salary profit
              FROM salespersons s
                 LEFT JOIN orders o      ON s.empid = o.empid
                 LEFT JOIN orderitems oi ON o.orderid = oi.orderid
                 LEFT JOIN inventory i   ON oi.partid = i.partid
              GROUP BY s.empid
                 , s.ename
                 , s.salary
              ) x
        /* WHERE x.r <= 2  -- for both top and second */

        /* where x.r = 1 -- for top only */

        /* where x.r = 2 -- for second place only */
       ) y

Open in new window

but only you can judge
0
 
LVL 74

Expert Comment

by:sdstuber
ID: 38862826
>>> Now that got the topprofited salesperson.

huh?

which query is "that"  ?

what you have said is the "top" appears to be the 2nd top.

what you have said is the "second top" appears to have nothing to do with the top profit but instead is salary based and bottom salary, not top.
0
 
LVL 48

Expert Comment

by:PortletPaul
ID: 38866731
sdstuber really deserved credit - sorry mate
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Why doesn't the Oracle optimizer use my index? Querying too much data Most Oracle developers know that an index is useful when you can use it to restrict your result set to a small number of the total rows in a table. So, the obvious side…
This article started out as an Experts-Exchange question, which then grew into a quick tip to go along with an IOUG presentation for the Collaborate confernce and then later grew again into a full blown article with expanded functionality and legacy…
This video explains at a high level about the four available data types in Oracle and how dates can be manipulated by the user to get data into and out of the database.
This video shows how to copy an entire tablespace from one database to another database using Transportable Tablespace functionality.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question