Solved

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

Posted on 2013-02-06
13
397 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
>>> 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
Comment Utility
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.

Join & Write a Comment

Suggested Solutions

Article by: Swadhin
From the Oracle SQL Reference (http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/queries006.htm) we are told that a join is a query that combines rows from two or more tables, views, or materialized views. This article provides a glimps…
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 set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.
Via a live example, show how to take different types of Oracle backups using RMAN.

771 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

12 Experts available now in Live!

Get 1:1 Help Now