0

Using the following tables,

Productivity:

PRODUCTIVITYID  PDATE   EMPLOYEEID  ROOMID  ROOMS_SOLD  SCR
81            03/26/2016    7499     21         56      43
82            03/26/2016    7566     42     -            -
102           03/26/2016    7499     22        434      22
101           03/26/2016    7566     21         43      53

ProductivityD:

PRODUCTIVITYID  WORKHRS MEALPANELTY DESCRIPTION
2                 50    4   -
21               6.4    1   -
102                6    -   -
81              1.32    -   -
101              3.6    -   - 

Rooms:

  ID    ROOM    PROPERTCODE
  22    102  6325
  41    103  6325
  42    104  6325
  43    105  6325

EMP:

EMPNO   ENAME   JOB     MGR     HIREDATE    SAL   COMM  DEPTNO
7566    JONES   MANAGER 7839    04/02/1981  2975    -   20
7788    SCOTT   ANALYST 7566    12/09/1982  3000    -   20
7902    FORD    ANALYST 7566    12/03/1981  3000    -   20
7369    SMITH   CLERK   7902    12/17/1980  800 -   20
7499    ALLEN   SALESMAN 7698   02/20/1981  1600    300 30

The following query is generating below output but I need to group employees and sum workhrs and then pivot RM_ROOM and RM_SCR

WITH pivot_data AS (
SELECT eNAME,workhrs,room, 'RM' as RM,SCR from PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID
            )
    SELECT *
    FROM   pivot_data
    PIVOT (
          MIN(room) as room,min(scr) as SCR      --<-- pivot_clause
          FOR RM--<-- pivot_for_clause        
         IN  ('RM')    --<-- pivot_in_clause         
)

Current Output:

ENAME   WORKHRS 'RM'_ROOM 'RM'_SCR
JONES   3.6       101        53
ALLEN   6         102        22
ALLEN   1.32      101        43

Desired Output:

    ENAME   WORKHRS 'RM'_ROOM 'RM'_SCR 'RM'_ROOM 'RM'_SCR
    JONES   3.6          101     53      -         -
   ALLEN    7.32         101     43     102       22
5
  • Some sample data would be nice. Commented Apr 2, 2016 at 10:52
  • @Tim The data is in ouput just need to transform last row and group first two columns Commented Apr 2, 2016 at 10:58
  • agreed on first comment , you don't show enough to get a clear answer. Show us the struct and data of your 2 tables Commented Apr 2, 2016 at 11:26
  • Your data and output don't match; you seem to be missing a record in rooms, with values (21, 101, 6325) ? Commented Apr 5, 2016 at 9:44
  • I may have missed that data to enter here but record exists in database. Commented Apr 5, 2016 at 9:47

2 Answers 2

4
+50

You are pivoting on a fixed value, the string literal 'RM', so you're really not doing anything useful in the pivot - the output is the same as you'd get from running the 'pivot_data' query on its own:

SELECT eNAME,workhrs,room, SCR from PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID;

ENAME    WORKHRS       ROOM        SCR
----- ---------- ---------- ----------
JONES        3.6        101         53
ALLEN       1.32        101         43
ALLEN          6        102         22

You want the aggregate workhrs for each employee, and a pivot of the rooms they sold. If you change that query to get the analytic sum of workhrs and a ranking of the room/scr values (and using modern join syntax) you get:

select e.ename, r.room, p.scr,
  sum(d.workhrs) over (partition by e.ename) as wrkhrs,
  rank() over (partition by e.ename order by r.room, p.scr) as rnk
from productivity p
join productivityd d on d.productivityid = p.productivityid
join emp e on e.empno=p.employeeid
join rooms r on r.id = p.roomid;

ENAME       ROOM        SCR     WRKHRS        RNK
----- ---------- ---------- ---------- ----------
ALLEN        101         43       7.32          1
ALLEN        102         22       7.32          2
JONES        101         53        3.6          1

You can then pivot on that generated rnk number:

with pivot_data as (
  select e.ename, r.room, p.scr,
    sum(d.workhrs) over (partition by e.ename) as wrkhrs,
    rank() over (partition by e.ename order by r.room, p.scr) as rnk
  from productivity p
  join productivityd d on d.productivityid = p.productivityid
  join emp e on e.empno=p.employeeid
  join rooms r on r.id = p.roomid
)
select *
from   pivot_data
pivot (
  min(room) as room, min(scr) as scr  --<-- pivot_clause
  for rnk                             --<-- pivot_for_clause        
  in  (1, 2, 3)                       --<-- pivot_in_clause         
);

ENAME     WRKHRS     1_ROOM      1_SCR     2_ROOM      2_SCR     3_ROOM      3_SCR
----- ---------- ---------- ---------- ---------- ---------- ---------- ----------
ALLEN       7.32        101         43        102         22                      
JONES        3.6        101         53                                            

You need to know the maximum number of rooms any employee may have - i.e. the highest rnk could ever be - and include all of those in the in clause. Which means you're likely to end up with empty columns, as in this example where there is no data for 3_room or 3_scr. You can't avoid that though, unless you get an XML result or generate the query dynamically.

Sign up to request clarification or add additional context in comments.

3 Comments

I have to build report and we can't use fix values of in clause
@MuhammadMuazzam - you have to have a fixed value. Or at least a fixed number of values, which is what I have here. A SQL query has to know how many columns will be in the result set before it is parsed and executed. You can generate the query dynamically but it's a bit messy, and whatever is handling the query needs to be able to deal with varying numbers of columns. Maybe your reporting tool can ignore the empty columns, or do the pivot itself?
Ok I will award if no other better than this solution arrived, meanwhile I have solution to build dynamic in clause using PIVOT.
0

What you are saying makes no sense. What do you mean by "pivot RM_ROOM"? So I have to guess. I am guessing you want to group employees and sum workhrs, and then pivot the result. The "Output" you show seems to be the output for pivot_data, your subquery.

Your answer will only have eNAME and for each of them, a count of hours worked. So you don't need to SELECT the room numbers in the pivot_data subquery. You only need eNAME and workhrs. Then it is a simple matter of using the PIVOT syntax:

WITH pivot_data AS (
    SELECT eNAME, workhrs FROM PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
    where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
    AND R.ID=P.ROOMID
            )
SELECT *
FROM   pivot_data
PIVOT (
        SUM(workhrs)
        FOR eNAME IN ('JONES', 'ALLEN')
      )
/

Output:

   'JONES'    'ALLEN'
---------- ----------
       3.6       7.32

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.