I need to Create 3 Variables from 1 Variable SQL Oracle SAP - sql

I’m working on creating three variables in the my Universe. The variables are Applications, Operating System, and Physical Location. The problem I’m running into is that all three of these is pulled from the same table and all of them are within the Value.
So the Table BMC_CORE_BMC_BASERELATIONSHIP has the variable Name. I am trying to pull all of the destination instance id's for the operating system when name is equal to SYSTEMOS.
My first guest was to use derived tables having each of the three a separate table with the following coding
“Operating System Relationship” Derive Table
SELECT
BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID
FROM
BMC_CORE_BMC_BASERELATIONSHIP
Where
BMC_CORE_BMC_BASERELATIONSHIP.Name = 'SYSTEMOS'
“Physical Location Relationship” Derive Table
SELECT
BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID
FROM
BMC_CORE_BMC_BASERELATIONSHIP
Where
BMC_CORE_BMC_BASERELATIONSHIP.Name = 'ELEMENTLOCATION'
“Applications Relationship” Derive Table
SELECT
BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID
FROM
BMC_CORE_BMC_BASERELATIONSHIP
Where
BMC_CORE_BMC_BASERELATIONSHIP.Name = 'APPLICATIONSYSTEMCOMPUTER'
However when I try pulling the variable in with the following syntax, only one of the variables will show up in Webi. The others are being nulled I figured out.
App Var
Case
WHEN CI_RELATED_CI.INSTANCEID ="Applications Relationship".DESTINATION_INSTANCEID
Then CI_RELATED_CI.NAME
END
Location Var
CASE
WHEN CI_RELATED_CI.INSTANCEID = "Physical Location Relationship".DESTINATION_INSTANCEID
THEN CI_RELATED_CI.NAME
END
OS Var
Case
WHEN CI_RELATED_CI.INSTANCEID ="Operating System Relationship".DESTINATION_INSTANCEID
Then CI_RELATED_CI.NAME
END
I was trying to think of a way to pull all of these into one derived table as separate variables, but so far I have been unsuccessful. Any thoughts or suggestions would be appreciated. I'm new so let me know if there is anything I can do to make my questions better.

you can use case like below or Decode,
select Case
WHEN BMC_CORE_BMC_BASERELATIONSHIP.Name = 'SYSTEMOS'
Then BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID
WHEN BMC_CORE_BMC_BASERELATIONSHIP.Name = 'ELEMENTLOCATION'
Then BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID
When BMC_CORE_BMC_BASERELATIONSHIP.Name = 'APPLICATIONSYSTEMCOMPUTER'
Then BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID
Else 'Ur Comments'
END
from BMC_CORE_BMC_BASERELATIONSHIP;
or Decode
select Decode( BMC_CORE_BMC_BASERELATIONSHIP.Name,'SYSTEMOS',BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID,'ELEMENTLOCATION',BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID,'APPLICATIONSYSTEMCOMPUTER',BMC_CORE_BMC_BASERELATIONSHIP.DESTINATION_INSTANCEID,else) from BMC_CORE_BMC_BASERELATIONSHIP;

am able to get the out put
create table BMC_CORE_BMC_BASERELATIONSHIP (name1 varchar2(100),id number);
insert into BMC_CORE_BMC_BASERELATIONSHIP (name1,id) values('SYSTEMOS',1);
insert into BMC_CORE_BMC_BASERELATIONSHIP (name1,id) values('ELEMENTLOCATION',2);
insert into BMC_CORE_BMC_BASERELATIONSHIP (name1,id) values('APPLICATIONSYSTEMCOMPUTER',3);
select Case
WHEN Name1 = 'SYSTEMOS'
Then id
WHEN Name1 = 'ELEMENTLOCATION'
Then id
When Name1 = 'APPLICATIONSYSTEMCOMPUTER'
Then id
Else id
END
from BMC_CORE_BMC_BASERELATIONSHIP ;
o/p #
1
2
3
select Decode(Name1,'SYSTEMOS',id,'ELEMENTLOCATION',id,'APPLICATIONSYSTEMCOMPUTER',id,id)
from BMC_CORE_BMC_BASERELATIONSHIP;
o/p #
1
2
3

Not sure if I understand you correctly and this is what you want... This is Oracle example where each column has own name or label. You can create table as select - just add create table as before the select and your column names will be the label names:
SELECT ename, empno,
(CASE deptno WHEN 10 THEN 'Accounting' END) dept10
, (CASE deptno WHEN 20 THEN 'Research' END) dept20
, (CASE deptno WHEN 30 THEN 'Sales' END) dept30
, (CASE deptno WHEN 40 THEN 'Operations' END) dept40
FROM scott.emp
ORDER BY ename
/
ENAME EMPNO DEPT10 DEPT20 DEPT30 DEPT40
---------------------------------------------------------------------
ADAMS 7876 Research
ALLEN 7499 Sales
BLAKE 7698 Sales
CLARK 7782 Accounting
.....

Related

Not a group by expression in my oracle SQL query

I have the following sql query that I m not able to process since this afternoon.
I have seen lot of threads about this issue but I m not getting it right, I believe that I m miss understanding this one topic that is shaming my day.
SELECT
cor.c_order_id, cor.totallines,cor.documentno,cbp.name
FROM
c_orderline col
LEFT JOIN c_order cor ON cor.c_order_id = col.c_order_id
LEFT join c_bpartner cbp on cbp.c_bpartner_id = cor.c_bpartner_id
WHERE
cor.issotrx = 'Y'
and cor.docstatus not in ('DR','IP')
AND cor.salesrep_id = 1037317
and col.qtyordered <> 0
and cor.dateordered between SYSDATE - 30 and SYSDATE + 30
AND col.c_orderline_id NOT IN (
SELECT
cil.c_orderline_id
FROM
c_invoiceline cil
WHERE
cil.c_orderline_id IS NOT NULL
)
group by cor.c_order_id, cor.documentno
order by cor.c_order_id, cor.documentno
What I m doing wrong ??
A simplified example, based on Scott's EMP table.
This is what you did:
SQL> select deptno, job
2 from emp
3 group by deptno;
select deptno, job
*
ERROR at line 1:
ORA-00979: not a GROUP BY expression
As you can see, Oracle marked the culprit - the JOB column.
Therefore, if you want to use a GROUP BY clause (which is correct, but - you'd get the same result using DISTINCT; these two should not be used together. GROUP BY is usually used with aggregates such as min, max, avg and such), then put all columns into the GROUP BY:
SQL> select deptno, job
2 from emp
3 group by deptno, job;
DEPTNO JOB
---------- ---------
20 CLERK
30 SALESMAN
20 MANAGER
30 CLERK
10 PRESIDENT
30 MANAGER
10 CLERK
10 MANAGER
20 ANALYST
9 rows selected.
Or, as I said - using DISTINCT:
SQL> select distinct deptno, job
2 from emp;
DEPTNO JOB
---------- ---------
20 CLERK
30 SALESMAN
20 MANAGER
30 CLERK
10 PRESIDENT
30 MANAGER
10 CLERK
10 MANAGER
20 ANALYST
9 rows selected.
SQL>
group by is used for aggregate functions like sum(), max(), min() etc. What value are you calculating in groups?
remove the group by and your query looks good besides that
To correct the error this query is producing you need to
group by cor.c_order_id, cor.totallines,cor.documentno,cbp.name
Group by all the columns that are in the select statement and are not part of aggregate function.
What else is a problem?
Here is the DEMO
In this demo you will see that the query works(with the correction I have suggested), but as I asked, what else is a problem to you. Do elaborate so we can help. Cheers!

SQL - how to transpose only some row values into column headers without pivot

I have a table similar to this:
stud_ID | first_name | last_name | email | col_num | user_value
1 tom smith 50 Retail
1 tom smith 60 Product
2 Sam wright 50 Retail
2 Sam wright 60 Sale
but need to convert it to: (basically transpose 'col_num' to column headers and change 50 to function, 60 to department)
stud_ID | first_name | last_name | email | Function | Department
1 tom smith Retail Product
2 Sam wright Retail Sale
Unfortunately Pivot doesn't work in my system, just wondering if there is any other way to do this please?
The code that I have so far (sorry for the long list):
SELECT c.person_id_external as stu_id,
c.lname,
c.fname,
c.mi,
a.cpnt_id,
a.cpnt_typ_id,
a.rev_dte,
a.rev_num,
cp.cpnt_title AS cpnt_desc,
a.compl_dte,
a.CMPL_STAT_ID,
b.cmpl_stat_desc,
b.PROVIDE_CRDT,
b.INITIATE_LEVEL1_SURVEY,
b.INITIATE_LEVEL3_SURVEY,
a.SCHD_ID,
a.TOTAL_HRS,
a.CREDIT_HRS,
a.CPE_HRS,
a.CONTACT_HRS,
a.TUITION,
a.INST_NAME,
--a.COMMENTS,
a.BASE_STUD_ID,
a.BASE_CPNT_TYP_ID,
a.BASE_CPNT_ID,
a.BASE_REV_DTE,
a.BASE_CMPL_STAT_ID,
a.BASE_COMPL_DTE,
a.ES_USER_NAME,
a.INTERNAL,
a.GRADE_OPT,
a.GRADE,
a.PMT_ORDER_TICKET_NO,
a.TICKET_SEQUENCE,
a.ORDER_ITEM_ID,
a.ESIG_MESSAGE,
a.ESIG_MEANING_CODE_ID,
a.ESIG_MEANING_CODE_DESC,
a.CPNT_KEY,
a.CURRENCY_CODE,
c.EMP_STAT_ID,
c.EMP_TYP_ID,
c.JL_ID,
c.JP_ID,
c.TARGET_JP_ID,
c.JOB_TITLE,
c.DMN_ID,
c.ORG_ID,
c.REGION_ID,
c.CO_ID,
c.NOTACTIVE,
c.ADDR,
c.CITY,
c.STATE,
c.POSTAL,
c.CNTRY,
c.SUPER,
c.COACH_STUD_ID,
c.HIRE_DTE,
c.TERM_DTE,
c.EMAIL_ADDR,
c.RESUME_LOCN,
c.COMMENTS,
c.SHIPPING_NAME,
c.SHIPPING_CONTACT_NAME,
c.SHIPPING_ADDR,
c.SHIPPING_ADDR1,
c.SHIPPING_CITY,
c.SHIPPING_STATE,
c.SHIPPING_POSTAL,
c.SHIPPING_CNTRY,
c.SHIPPING_PHON_NUM,
c.SHIPPING_FAX_NUM,
c.SHIPPING_EMAIL_ADDR,
c.STUD_PSWD,
c.PIN,
c.PIN_DATE,
c.ENCRYPTED,
c.HAS_ACCESS,
c.BILLING_NAME,
c.BILLING_CONTACT_NAME,
c.BILLING_ADDR,
c.BILLING_ADDR1,
c.BILLING_CITY,
c.BILLING_STATE,
c.BILLING_POSTAL,
c.BILLING_CNTRY,
c.BILLING_PHON_NUM,
c.BILLING_FAX_NUM,
c.BILLING_EMAIL_ADDR,
c.SELF_REGISTRATION,
c.SELF_REGISTRATION_DATE,
c.ACCESS_TO_ORG_FIN_ACT,
c.NOTIFY_DEV_PLAN_ITEM_ADD,
c.NOTIFY_DEV_PLAN_ITEM_MOD,
c.NOTIFY_DEV_PLAN_ITEM_REMOVE,
c.NOTIFY_WHEN_SUB_ITEM_COMPLETE,
c.NOTIFY_WHEN_SUB_ITEM_FAILURE,
c.LOCKED,
c.PASSWORD_EXP_DATE,
c.SECURITY_QUESTION,
c.SECURITY_ANSWER,
c.ROLE_ID,
c.IMAGE_ID,
c.GENDER,
c.PAST_SERVICE,
c.LST_UNLOCK_TSTMP,
c.MANAGE_SUB_SP,
c.MANAGE_OWN_SP,
d.col_num,
d.user_value
FROM pa_cpnt_evthst a,
pa_cmpl_stat b,
pa_student c,
pv_course cp,
pa_stud_user d
WHERE a.cmpl_stat_id = b.cmpl_stat_id
AND a.stud_id = c.stud_id
AND cp.cpnt_typ_id(+) = a.cpnt_typ_id
AND cp.cpnt_id(+) = a.cpnt_id
AND cp.rev_dte(+) = a.rev_dte
AND a.CPNT_TYP_ID != 'SYSTEM_PROGRAM_ENTITY'
AND c.stud_id = d.stud_id
AND d.col_num in ('10','30','50','60')
I would just use conditional aggregation:
select stud_ID, first_name, last_name, email,
max(case when col_num = 50 then user_value end) as function,
max(case when col_num = 60 then user_value end) as department
from t
group by stud_ID, first_name, last_name, email;
Your code seems to have nothing to do with the sample data. I do notice however that you are using implicit join syntax. You really need to learn how to use proper, explicit, standard JOIN syntax.
I'm assuming you have Sql Server 2000 or 2003. What you need to do in that case is create a script with one cursor.
This cursor will create a text with something like this:
string var = "CREATE TABLE #Report (Col1 VARCHAR(20), Col2, VARCHAR(20), " + ColumnName
That way you can create a temp table on the fly, at the end you will need to do a Select of your temp table to get your pivot table ready.
Its not that easy if you are not familiar with cursors.
OR
if there are only few values on your 'pivot' column and they are not going to grow you can also do something like this:
Pivot using SQL Server 2000
I'm unable to understand your code, so I'll just assume the table mentioned in the sample data as stud(because of stud_id).
So here is what I think can do the work of pivot.
SELECT ISNULL(s1.stud_ID, s2.stud_id),
ISNULL(s1.first_name, s2.first_name),
ISNULL(s1.last_name, s2.last_name),
ISNULL(s1.email, s2.email),
s1.user_value as [Function], s2.user_value as Department
FROM stud s1 OUTER JOIN stud s2
ON s1.stud_ID = s2.stud_ID -- Assuming stud_ID is primary key, else join on all primary keys
AND s1.col_num = 50 AND s2.col_num = 60
Explanation: I'm just trying to simulate here what PIVOT does. For every column you want, you create a new table in the JOIN and constaint it to only one value in your col_num column. For example, if there are no values for 50 in s1, the OUTER JOIN will get make it NULL and we need to pull records from s2.
Note: If you need more than 2 new columns, then you can use COALESCE instead of ISNULL

Oracle sql order by with case statement

I am facing difficulty in understanding oracle(12c) sql order by clause with case statement.
I have a table with the below data,
SELECT DEPT_NO, DEPT_NAME FROM SORTNG_LOGIC;
DEPT_NO DEPT_NAME
---------- --------------------
1 FINANCE
2 ACCOUNT
3 HUMAN RESOURCE
4 AUDIT
5 TRAINING
I am executing the below sql query for this table to add custom order, on oracle sql developer.
SELECT DEPT_NO, DEPT_NAME FROM SORTNG_LOGIC ORDER BY (
CASE DEPT_NAME
WHEN 'ACCOUNT' THEN '1'
WHEN 'AUDIT' THEN '2'
WHEN 'FINANCE' THEN '3'
ELSE '4' END
)DESC;
This is giving the below result :
DEPT_NO DEPT_NAME
---------- --------------------
3 HUMAN RESOURCE
5 TRAINING
1 FINANCE
4 AUDIT
2 ACCOUNT
But I expected that, the result should be
DEPT_NO DEPT_NAME
---------- --------------------
5 TRAINING
3 HUMAN RESOURCE
1 FINANCE
4 AUDIT
2 ACCOUNT
As I am sorting the dept_name in descending order, I thought'Training' should be above 'human resource'.
Where is my understanding going wrong? Could someone please explain this in detail?
If you want the department name in descending order, then you have to include that information in the query:
ORDER BY (CASE DEPT_NAME
WHEN 'ACCOUNT' THEN 1
WHEN 'AUDIT' THEN 2
WHEN 'FINANCE' THEN 3
ELSE 4
END) DESC,
DEPT_NAME DESC;
There is no reason for the value of the CASE to be a character string. The logic really calls for a number. If you use strings, then values larger than 9 will not work as you expect them to.
Try this with decode function, basically does the same thing.
SELECT DEPT_NO, DEPT_NAME
FROM SORTNG_LOGIC
ORDER BY
decode (DEPT_NAME,'ACCOUNT','1','AUDIT','2','FINANCE','3','4') DESC;

Using 'case expression column' in where clause

SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */
WHERE department = 'SALES'
This fails:
ORA-00904: "%s: invalid identifier"
Is there a way to overcome this limitation in Oracle 10.2 SQL ?
How to use the 'case expression column' in where clause ?
The reason for this error is that SQL SELECT statements are logically * processed in the following order:
FROM: selection of one table or many JOINed ones and all rows combinations that match the ON conditions.
WHERE: conditions are evaluated and rows that do not match are removed.
GROUP BY: rows are grouped (and every group collapses to one row)
HAVING: conditions are evaluated and rows that do not match are removed.
SELECT: list of columns is evaluated.
DISTINCT: duplicate rows are removed (if it's a SELECT DISTINCT statement)
UNION, EXCEPT, INTERSECT: the action of that operand is taken upon the rows of sub-SELECT statements. For example, if it's a UNION, all rows are gathered (and duplicates eliminated unless it's a UNION ALL) after all sub-SELECT statements are evaluated. Accordingly for the EXCEPT or INTERSECT cases.
ORDER BY: rows are ordered.
Therefore, you can't use in WHERE clause, something that hasn't been populated or calculated yet. See also this question: oracle-sql-clause-evaluation-order
* logically processed: Note that database engines may as well choose another order of evaluation for a query (and that's what they usually do!) The only restriction is that the results should be the same as if the above order was used.
Solution is to enclose the query in another one:
SELECT *
FROM
( SELECT ename
, job
, CASE deptno
WHEN 10 THEN 'ACCOUNTS'
WHEN 20 THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp
) tmp
WHERE department = 'SALES' ;
or to duplicate the calculation in the WHERE condition:
SELECT ename
, job
, CASE deptno
WHEN 10 THEN 'ACCOUNTS'
WHEN 20 THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp
WHERE
CASE deptno
WHEN 10 THEN 'ACCOUNTS'
WHEN 20 THEN 'SALES'
ELSE 'UNKNOWN'
END = 'SALES' ;
I guess this is a simplified version of your query or you could use:
SELECT ename
, job
, 'SALES' AS department
FROM emp
WHERE deptno = 20 ;
Your table does not contain a column "department" and thus you can not reference it in your where clause. Use deptno instead.
SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */ where deptno = 20;
This work for me :
SELECT ename, job
FROM emp
WHERE CASE WHEN deptno = 10 THEN 'ACCOUNTS'
WHEN deptno = 20 THEN 'SALES'
ELSE 'UNKNOWN'
END
= 'SALES'
select emp_.*
from (SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */ ) emp_ where emp_.department='UNKNOWN';
try:
SQL> SELECT ename
2 , job
3 , CASE
4 WHEN deptno = 10
5 THEN 'ACCOUNTS'
6 WHEN deptno = 20
7 THEN 'SALES'
12 ELSE 'UNKNOWN'
13 END AS department
14 FROM emp /* !!! */ where department = 'SALES';
Oracle tries to filter the number of records to be scanned from table by going for the where clause first before select that is why your query fails. Moreover, your query would have never returned rows with department - "Accounts or Unknown" because of the filter Department="SALES"
Try below instead, that will be easy to be fetched by Engine :
SELECT ename, job,'SALES' AS department
FROM emp
WHERE deptno = 20;

Retrieving monthly data for different types

I'm working on a report that needs to retrieve
all employees
new additions this month
new additions this year
terminations this month
terminations this year
All of these are split up by department (new marketing emps, new sales, etc).
In total, there'll be about 23 columns..
I'm using a temporary table by populating each field with an update. Here's a simplified example of what I'm doing. Employee table has most of the values needed (hiredate, termdate, etc). There's actually a join in each update and some more conditions.
update #tmptbl
set MtdHiresSales = select count(empid) from emp e where e.dept = 012
and hiredate between start_of_month() and getdate()
-- more predicates
set MtdHiresMkting = ...repeat... with e.dept=013
I'm sure there's a better way because there's a lot of code duplication. Are temporary tables appropriate in this case? I'm not sure how it could be done without one. Any suggestions?
You can probably use a CASE for this. For example:
SELECT
SUM(CASE WHEN e.dept=012
AND Hiredate between Start_of_Month() and Getdate()
AND...
THEN 1 ELSE 0 END) AS 'MtdHiresSales',
...
FROM ...
WHERE ...
You could use a common table expression to encapsulate the employee counting code...
WITH
employee_counts
AS
(
SELECT
dept AS "dept",
x AS "x",
COUNT(empid) AS "employees"
FROM
emp
WHERE
hiredate BETWEEN start_of_month() AND getdate()
-- etc, etc
GROUP BY
dept,
x
)
UPDATE
myTable
SET
MtdHiresSales = (SELECT employees FROM employee_counts WHERE dept = 012 AND x = myTable.y),
MtdHiresMkting = (SELECT employees FROM employee_counts WHERE dept = 013 AND x = myTable.y)
Maybe I'm confused or not seeing something, but why not just use aggregates?
SELECT count(*) as employeesPerDept, deptId
from mudkips
group by deptId
giving (for my sample data)
employeesPerDept deptId
6 100
4 200
and
select deptId, count(*) as empsHired, month(hiredate) as monthHired,
year(hireDate) as yearHired
from mudkips
group by deptId, month(hireDate), year(hireDate)
which then is
deptId empsHired monthHired yearHired
100 4 1 2010
100 1 1 2011
100 1 2 2010
200 2 1 2010
200 1 2 2010
200 1 3 2010