?
Solved

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

Posted on 2013-02-06
13
Medium Priority
?
409 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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 49

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 49

Accepted Solution

by:
PortletPaul earned 1000 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 49

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 49

Expert Comment

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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

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…
How to Unravel a Tricky Query Introduction If you browse through the Oracle zones or any of the other database-related zones you'll come across some complicated solutions and sometimes you'll just have to wonder how anyone came up with them.  …
This video explains at a high level with the mandatory Oracle Memory processes are as well as touching on some of the more common optional ones.
This video explains what a user managed backup is and shows how to take one, providing a couple of simple example scripts.
Suggested Courses

777 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