how to populate internal table with multiple database tables? - abap

I have declared an internal table.
DATA ITAB_DEPT TYPE TABLE OF ZCLOUD9_DEPT WITH HEADER LINE.
SELECT A~DEPT_ID A~DEPT_NAME A~DEPT_NO A~EMP_ID B~FIRST_NAME B~LAST_NAME
INTO TABLE ITAB_DEPT FROM ZCLOUD9_DEPT AS A
INNER JOIN ZCLOUD9_EMP AS B
ON A~EMP_ID = B~EMP_ID
WHERE A~DEPT_ID = MEM_DEPT_ID.
WRITE AT: /1 'Department ID' , 15 'Dept Name' , 30 'Tel No' , 40 'Dept I/C ID' , 50 'Dept I/C'.
uline.
LOOP AT ITAB_DEPT.
WRITE AT: /1 ITAB_DEPT-DEPT_ID , 15 ITAB_DEPT-DEPT_NAME ,
30 ITAB_DEPT-DEPT_NO, 40 ITAB_DEPT-EMP_ID , 50 ITAB_DEPT-FIRST_NAME , 59 ITAB_DEPT-LAST_NAME.
when i have activate the program, the syntax error states that the itab_dept does not have a component called first_name/last_name

You should declare your 'ITAB_DEPT' similar to this.
types: begin of struct_dept.
include type zcloud9_dept.
include type zcloud9_emp.
types: end of struct_dept.
data: itab_dept type table of struct_dept with header line.
Right now, 'ITAB_DEPT' only contains the fields of 'ZCLOUD9_DEPT' table. You also need the fields of 'ZCLOUD9_EMP' to join them.
This may not work right out of the box, but it should put you on the right path.

Related

Assign custom labels to sql query

This is a pretty simple question, I think, but I cannot find an answer for it here, or through online searching.
I am running a count query, and am having trouble with value labels and column headings
Query is
SELECT
mail_code AS "code",
COUNT(mail_code) AS "count"
FROM data.base
GROUP BY mail_code
;
I get back:
C Count
- -----
Y 110
X 785
Z 92
Questions:
How do I get the first variable (code) to display its full name, instead of a single letter?
How do I change Y, X, and Z to read "phone," "mail," and "email" ...or anything else for that matter?
The length of the mail_code variable is 1 byte...is that why only the first letter is showing up as my varname?
...I was initially warned that based on my title, it might get downvoted. OK, but I tried to look elsewhere for the answer and could not find it, IE I tried due diligence.
Thank you in advance.
Mostly, they keep a look-up table with foreign - primary key relationship. i.e. write explanation in a table with code_name and explanation columns
with values X , phone ; Y, mail : Z , email respectively,
and Join them with a SQL statement :
select d.mail_code as "code", c.explanation as "communication type", count(1) as "count"
from data_base d inner join codes c on ( d.mail_code = c.mail_code )
group by d.mail_code, c.explanation;
Where DDLs are as following to create tables :
create table codes(mail_code varchar2(1) primary key,explanation varchar2(15));
create table data_base( mail_code varchar2(1) references codes(mail_code));
Demo
Thank you all, I got about 75% of the way there.
Syntax:
COLUMN mail_code FORMAT A10
SELECT
DECODE (mail_code,
'X', 'mail',
'Y', 'phon',
'Z', 'emai') AS "code",
COUNT(*) AS "count"
FROM data.base
GROUP BY mail_code
;
Returned
code count
---- -----
mail 110
phon 785
emai 92
Double quotes are needed b/c Oracle. It'll work to change name to 'code' wo double quotes but comes up as all caps (CODE) wo them, and I can choose w double quotes.
Thank you all for your help with this!

How to combine multiple rows from three tables into one single string in SQL?

I have three tables that store different kinds of data according to an admission process.
The first table ([dbo].[Inscripciones_Pregrado]) stores the basic contact info of the future student. The second table ([dbo].[Checklist_Documentos]) stores the names and ID's for the documents that the student must have to complete the admission process. The third table ([dbo].[Checklist_Pregrado]) stores the documents that the student has effectively brought to the admissions office.
I need to combine this info so that we can export an excel file holding all the contact info, and the document's checklist for each student.
So, let's say table 1 haves 4 records:
[dbo].[Inscripciones_Pregrado]
The second table ([dbo].[Checklist_Documentos]) haves eight records, different types of requested documents:
And the third table ([dbo].[Checklist_Pregrado]) haves 16 records:
What I need is that this three tables get combined according to the aspirant's ID:
So far, I've tried to different types of codes:
Code 1
SELECT
[dbo].[Inscripciones_Pregrado].[ID],
[dbo].[Inscripciones_Pregrado].[Name],
[dbo].[Inscripciones_Pregrado].[ProgramID],
[dbo].[Checklist_Documentos].[Document]
FROM [dbo].[Inscripciones_Pregrado]
INNER JOIN
[dbo].[Checklist_Pregrado]
ON [dbo].[Checklist_Pregrado].[IdForm] = [dbo].[Inscripciones_Pregrado].[ID]
INNER JOIN
[dbo].[Checklist_Documentos]
ON [dbo].[Checklist_Documentos].[ID] = [dbo].[Checklist_Pregrado].[IdDoc]
This one gets one line per each document, so the name and other records are repeated according to the number of documents that the aspirant has on his folder.
Code 2
SELECT
[dbo].[Inscripciones_Pregrado].[ID],
[dbo].[Inscripciones_Pregrado].[Nombres],
[dbo].[Inscripciones_Pregrado].[Apellido1],
(STUFF((SELECT CAST(', ' + [dbo].[Checklist_Pregrado].[IdDocumento] AS varchar(max))
FROM [dbo].[Checklist_Pregrado]
WHERE([dbo].[Inscripciones_Pregrado].[ID] = [dbo].[Checklist_Pregrado].[IdForm])
FOR XML PATH ('')), 1, 2, '')) AS [Docs]
FROM [dbo].[Inscripciones_Pregrado]
This code get's and error:
Conversion failed when converting the varchar value ', ' to data type int.
I appreciate all your help and comments.
Thanks
For your Code 2, you can fix the error by doing the CAST before you do the concatenation.
In other words:
(STUFF((SELECT ', ' + CAST([dbo].[Checklist_Pregrado].[IdDocumento] AS varchar(max))
#Tab Alleman gave me the hint on the answer, I haven't noticed that error in the writing. It solved the issue, but the code would only bring the document's ID from the second table ([dbo].[Checklist_Documentos]) So I added an INNER JOIN to combine the data:
SELECT
[dbo].[Inscripciones_Pregrado].[ID],
[dbo].[Inscripciones_Pregrado].[Nombres],
[dbo].[Inscripciones_Pregrado].[Apellido1],
(STUFF((SELECT ', ' + CAST([dbo].[Checklist_Documentos].[Documento] AS varchar(max))
FROM [dbo].[Checklist_Pregrado]
INNER JOIN
[dbo].[Checklist_Documentos]
ON [dbo].[Checklist_Documentos].[ID] = [dbo].[Checklist_Pregrado].[IdDocumento]
WHERE([dbo].[Inscripciones_Pregrado].[ID] = [dbo].[Checklist_Pregrado].[IdForm])
FOR XML PATH ('')), 1, 2, '')) AS [Docs]
FROM [dbo].[Inscripciones_Pregrado]

Extract multiple strings from a free text field

Let's say I have a free text field called 'Note' and contains "ABC:5/52 , *back, orders received"
How do I extract '5/52' and 'back' and place them in two separate columns?
Here's what I wanted to achieve
QUERY:-
SELECT *, SUBSTRING(Note, CHARINDEX(':', Note)+1, 4) as ABC,
SUBSTRING(Note, CHARINDEX('*', Note)+1, 4) as Ret_Stat
, CHARINDEX(':', Note) AS [Colon Index]
FROM [AdventureWorks2012].[Sales].[Comments]
RESULT:-
Note ABC Ret_Stat
ABC:3/52, To give more explanation, *back 3/52 back
ABC:3wks, To debrief, *back, r/v 3wks back
ABC:13/09/16, see cm, *back, new referral 13/0 back
My issue is i wanted to extract 3/52, 3wks, and 13/09/16 but my end result's only 13/10.
I'd like to ask how to achieve this? as the condition of extraction may vary from 4 to 8 characters after ABC: and the table contains thousands of rows of data
Need advice. THank you.
Here's an example of what you want to do. You may have to modify this a little as I don't have a lot of sample data to go on.
Test Data
IF OBJECT_ID('tempdb..#TempData') IS NOT NULL DROP TABLE #TempData
GO
CREATE TABLE #TempData (Notes varchar(100))
INSERT INTO #TempData (Notes)
VALUES
('This is the first "ABC:5/52 string *back, orders received')
,('*back, orders receivedThis"ABC:5/52 string is the second one')
,('You guessed it, this *back, orders received is the third "ABC:5/52 string')
Query
SELECT
CHARINDEX('*',Notes) AsteriskLocation
,SUBSTRING(Notes,CHARINDEX('*',Notes)+1,4) AfterAsterisk
,CHARINDEX(':',Notes) ColonLocation
,SUBSTRING(Notes,CHARINDEX(':',Notes)+1,4) AfterColon
FROM #TempData
Result
AsteriskLocation AfterAsterisk ColonLocation AfterColon
36 back 23 5/52
1 back 31 5/52
22 back 62 5/52
I've left the locations separately so that you can see how they're used in the query. You could search for strings too using the same method.

Data type mismatch while fetching data from one table into another

I'm trying to get data from a table CustomerCase of database TD_EDD; into a table CustomerCase of database DsVelocity. The problem is whenever I try to get the data, error message is generated because in CustomerCase table of TD_EDD database, there are 3 columns: LOB, ReferralSource and CaseType of type varchar; while in CustomerCase table of DsVelocity database, the 3 matching columns are LOBID, ReferralSourceID and CaseTypeID and are of type int.
I've simply tried to execute this query:
INSERT INTO [DsVelocity].[dbo].[CustomerCase]
([CustomerID]
,[Tier]
,[EscalationDate]
,[ReferralSourceID]
,[ICMSID]
,[LOBID]
,[TriggerRC]
,[TriggerAccount]
,[Project]
,[CaseTypeID]
,[DateDue]
,[SARFiledYes]
,[SARFiledNo]
,[TeamLead]
,[SARAmount]
,[InitialNotes]
,[WorkFlowStatus]
,[CaseDecision]
,[AccountsReviewed]
,[ActionDate]
,[SecondLvlReview]
,[CompanyType]
,[IfOther]
,[ClientType]
,[MergeFlag]
,[MergeCaseID]
,[AMLREP]
,[HighRiskYes]
,[HighRiskNo]
,[AutoCreated]
,[FileName]
,[SourceRefDate]
,[SourceRefID]
,[ETMAdd]
,[ETMRemove]
,[ETMDate]
,[Investigator]
,[InUseBy])
SELECT [CustomerID]
,[Tier]
,[EscalationDate]
,[ReferralSource]
,[ICMSID]
,[LOB]
,[TriggerRC#]
,[TriggerAccount]
,[Project]
,[CaseType]
,[DateDue]
,[SARFiledYes]
,[SARFiledNo]
,[TeamLead]
,[SARAmount]
,[InitialNotes]
,[WorkFlowStatus]
,[CaseDecision]
,[AccountsReviewed]
,[ActionDate]
,[2ndLvlReview]
,[CompanyType]
,[IfOther]
,[ClientType]
,[MergeFlag]
,[MergeCaseID]
,[AMLREP]
,[HighRiskYes]
,[HighRiskNo]
,[AutoCreated]
,[FileName]
,[SourceRefDate]
,[SourceRefID]
,[ETMAdd]
,[ETMRemove]
,[ETMDate]
,[Investigator]
,[InUseBy]
FROM [TD_EDD].[dbo].[CustomerCase]
and then ran into the following error:
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value 'CRR' to data type int.
CRR is a data in the column ReferralSource.
Similar messages may appear in case of LOB and CaseType columns
The database server I'm using is MSSQL Server 2008 R2.
What is the solution to this problem???
EDIT-1: Tried using Inner Join with LOB, CaseType and ReferralSource tables. Now the error has disappeared, query ran ok, but I get data from only 2 rows. I can't understand why?????? I had more than 40 data in the [TD_EDD].[dbo].[CustomerCase] table, so all these data were supposed to be passed to the [DsVelocity].[dbo].[CustomerCase] table. What's wrong?
EDIT-2: Got it. CaseType column in [TD_EDD].[dbo].[CustomerCase] had mostly NULL values, only 2 rows had valid data. Hence, only 2 rows were sent to [DsVelocity].[dbo].[CustomerCase] becasue no corresponding ID match can be made for null values. I guess I figured it out myself. Thanks everyone.
You could try casting as already suggested or probably you're referring the wrong field name, like (I shall focus only on the one that has an error):
SELECT
,[ReferralSourceID]
,[LOBID]
,[CaseTypeID]
FROM [TD_EDD].[dbo].[CustomerCase]
Instead of ReferralSource use ReferralSourceID, instead of LOB use LOBID and instead of CaseType use CaseTypeID.
Or probably you need to reference the Reference Table on those fields like:
SELECT
,[ReferralSourceID]
,[LOBID]
,[CaseTypeID]
FROM [TD_EDD].[dbo].[CustomerCase] CC
INNER JOIN Referral R
ON CC.ReferralSource = R.ReferralSource
INNER JOIN LobTbl L
ON CC.LOB = L.LOB
INNER JOIN CaseTypeTbl C
ON CC.CaseType = C.CaseType
Try casting your varchar columns to int (assuming the data in your source columns is valid for int columns in target)
SELECT CAST(ReferralSource AS int),
CAST(LOB AS int),
CAST(CaseType AS int)
--etc

PL SQL Pivot Table VS Custom Json solution

I'm at a point within one of my Oracle APEX projects where I need to implement different levels of security for specific individuals for specific applications.
To start, I created a cartesian containing the information from the user table, the app table, and the role table.
It looks like this:
SELECT
A.user_id, B.app_id, C.role_id
FROM user A, app B, role C
ORDER BY A.user_id ASC, B.app_id ASC, C.role_id ASC
This allows me to return EVERY combination of user, app, and role. w/o using a where clause it returns over 303k rows. currently almost 500 users, 6 roles, and over 100 apps.
when I select from this view for a specific user its returning in approximately 10 ms which is acceptable.
Now, I also have a vw that stores each user's app/role assignment. I've joined this table to the cartesian in the following fashion.
SELECT
A.*,
DECODE(B.app_right_id, null, 0, 1) AS user_access
FROM
vw_user_app_role A -- My cartesian view
LEFT JOIN vw_tbl_user_app_role B
ON A.user_id = B.user_id
AND A.app_id = B.app_id
AND A.role_id = B.role_id
This returns a very usable set of data that resembles
user_id app_id role_id user_access
50 5 1 0
50 10 2 1
50 15 3 1
75 5 1 1
75 10 2 0
75 15 3 0
I'm considering what my next step should be, If I should create a pivot of the data where the app_id would be the row, the role_id would be the columns, and the user_access would be the "data". The "data" would ultimately be rendered as a check box on a website with the appropriate row/column headings.
I'm also considering using a pure ajax/json solution where I will build the json string using pl sql and return the entire string to the client to be processed via jquery.
I'm concerned with the difficulty of the first option (i'm very new to pl sql, and I'm unsure of how to generate a pivot table to be used in this version of oracle (v 10) ) and I'm concerned with the expense of creating an entire json string that will contain so much data.
Any suggestions would be greatly appreciated.
EDIT
I've achieved the pivot table that I desired via the following sql:
SELECT
B.application_nm,
A.user_id,
MAX(DECODE(b.role_name, 'role 1', A.USER_ACCESS, NULL)) "role 1",
MAX(DECODE(b.role_name, 'role 2', A.USER_ACCESS, NULL)) "role 2",
MAX(DECODE(b.role_name, 'role 3', A.USER_ACCESS, NULL)) "role 3",
MAX(DECODE(b.role_name, 'role 4', A.USER_ACCESS, NULL)) "role 4",
MAX(DECODE(b.role_name, 'role 5', A.USER_ACCESS, NULL)) "role 5",
MAX(DECODE(b.role_name, 'role 6', A.USER_ACCESS, NULL)) "role 6"
FROM
vw_user_app_access A LEFT JOIN vw_tbl_app B ON A.app_id = B.app_id
LEFT JOIN vw_tbl_roles C ON A.role_id = C.role_id
GROUP BY B.application_name, A.user_id
ORDER BY A.user_id DESC
Only problem is when in the future we have to add 'role 7'. I have to then go back into this query and add the line MAX(DECODE(b.role_name, 'role 7', A.USER_ACCESS, NULL)) "role 7"
Thinking ahead, this may be an inconvenience, but considering APEX's framework, I would have to go into the report any way to update the number of columns manually i believe.
I'm thinking this may be the "best" solution for now, unless anyone has any other suggestions...
It is possible for an Apex report region based on a dynamic SQL query to return a different number of columns as the query changes. I have set up a simple demo on apex.oracle.com. Type a new column name into the Columns tabular form and press "Add Row", and the Matrix report is re-drawn with an extra column of that name.
You have to:
Base the report on a function that returns the SQL to be run as a string
Select the region attribute "Use Generic Column Names (parse query at runtime only)"
Set the report Headings Type to PL/SQL and then use a function to dynamically return the required column headings as a colon-separated list. Note that this can be different from the column name, although my example uses the same text for both.
If my example isn't clear enough I'll add more info later - I'm out of time now.