Solved

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

Posted on 2013-02-06
13
398 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
  • 5
  • 4
  • 4
13 Comments
 
LVL 73

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 73

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
 
LVL 73

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
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 
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 73

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 73

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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

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

Suggested Solutions

This post first appeared at Oracleinaction  (http://oracleinaction.com/undo-and-redo-in-oracle/)by Anju Garg (Myself). I  will demonstrate that undo for DML’s is stored both in undo tablespace and online redo logs. Then, we will analyze the reaso…
From implementing a password expiration date, to datatype conversions and file export options, these are some useful settings I've found in Jasper Server.
This video shows how to Export data from an Oracle database using the Original Export Utility.  The corresponding Import utility, which works the same way is referenced, but not demonstrated.
This video shows how to copy an entire tablespace from one database to another database using Transportable Tablespace functionality.

912 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now