• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 420
  • Last Modified:

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

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
ocdc
Asked:
ocdc
  • 5
  • 4
  • 4
1 Solution
 
sdstuberCommented:
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
 
sdstuberCommented:
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
 
ocdcAuthor Commented:
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
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
sdstuberCommented:
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
 
PortletPaulfreelancerCommented:
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
 
ocdcAuthor Commented:
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
 
PortletPaulfreelancerCommented:
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
 
ocdcAuthor Commented:
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
 
sdstuberCommented:
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
 
ocdcAuthor Commented:
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
 
PortletPaulfreelancerCommented:
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
 
sdstuberCommented:
>>> 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
 
PortletPaulfreelancerCommented:
sdstuber really deserved credit - sorry mate
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

  • 5
  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now