Re-qwrite Oracle SQL using ANSI Oracle - sql

I am new to oracle and sql, I would like to know how can I re-write the following sql query using Oracle ANSI join conditions.
SELECT emp_no,
(SELECT emp_title
FROM hr_v_employee
WHERE organization_code LIKE
SUBSTR (emp.depart_code, 0, 4) || '00'
AND emp_position_code =
(SELECT MIN (emp_position_code)
FROM hr_v_employee
WHERE organization_code LIKE
SUBSTR (emp.depart_code,
0,
4
)
|| '00'))
|| ' '
|| NVL (employee_deptartment, '-')
employee_deptartment
FROM employees e, employee_details o
WHERE emp.emp_no = o.emp_no(+)
Edit 1
This what I have tried, my question is it possible to use join or ANSI standard for sub-query as well?
SELECT emp_no,
(SELECT emp_title
FROM hr_v_employee
WHERE organization_code LIKE
SUBSTR (emp.depart_code, 0, 4) || '00'
AND emp_position_code =
(SELECT MIN (emp_position_code)
FROM hr_v_employee
WHERE organization_code LIKE
SUBSTR (emp.depart_code,
0,
4
)
|| '00'))
|| ' '
|| NVL (employee_deptartment, '-')
employee_deptartment
FROM employees e left outer join employee_details o (emp.emp_no = o.emp_no)

Apart from the missing ON keyword for the LEFT OUTER JOIN, your query should be fine:
SELECT emp_no,
(SELECT emp_title
FROM hr_v_employee
WHERE organization_code LIKE SUBSTR(emp.depart_code,
0,
4) || '00'
AND emp_position_code =
(SELECT MIN(emp_position_code)
FROM hr_v_employee
WHERE organization_code LIKE SUBSTR(emp.depart_code,
0,
4) || '00')) || ' ' ||
NVL(employee_deptartment,
'-') employee_deptartment
FROM employees e
LEFT OUTER JOIN employee_details o
ON emp.emp_no = o.emp_no
Please note that you have a typo in your column names - it should be called employee_department instead of employee_deptartment.

Related

Oracle connect by function alternate in Postgres

I have below query in oracle, I want to migrate into Postgres, Can anyone please help me on that?
The only challenging part is Connect by command. Its not supported in Postgres
WITH readyForHouseKeeper AS (
SELECT regexp_substr(system_file_path, '^.*/') AS path
FROM cognito.patent p
JOIN cognito.pat_tracking pt
ON p.ref_id = pt.pat_ref_id
AND p.language = 'es'
AND p.stage_id=80
AND pt.stage_id=80
AND pt.status_date BETWEEN (localtimestamp - INTERVAL '2' MONTH) AND (localtimestamp - INTERVAL '1' MONTH) -- between 60days and 30 days -- Frontfile
AND rownum < 50001
ORDER BY pt.status_date
)
SELECT h.path||' '|| fileType ||' 30 * f rm'
FROM readyForHouseKeeper h,
(
SELECT trim(regexp_substr(fileType,'[^;]+', 1, LEVEL)) AS fileType
FROM ( SELECT 'stripped_cxml_*;MachineOutput_NameFile_cxml_*;Low_Confidence_*;*ContentFile*' AS fileType)
CONNECT BY instr(fileType, ';', 1, LEVEL - 1) > 0
)
No need for connect by or a recursive query, just turn the string into rows using string_to_table()
....
SELECT h.path||' '|| t.fileType ||' 30 * f rm'
from readyForHouseKeeper h,
lateral string_to_table('stripped_cxml_*;MachineOutput_NameFile_cxml_*;Low_Confidence_*;*ContentFile*', ';') as t(filetype)
Although I prefer an explicit cross join:
SELECT h.path||' '|| t.fileType ||' 30 * f rm'
from readyForHouseKeeper h --<< no comma!
cross join lateral string_to_table(...) as t(filetype)
Or if you are using an older Postgres version:
....
SELECT h.path||' '|| t.fileType ||' 30 * f rm'
from readyForHouseKeeper h,
lateral unnest(string_to_array('stripped_cxml_*;MachineOutput_NameFile_cxml_*;Low_Confidence_*;*ContentFile*', ';')) as t(filetype)

How to split result of coalesce function in two columns in SQL

We have three tables
Person_Table
Phone_Table
Primary_Phone_Table
All the phone number(primary and non-primary Table) is in format "areacode-Phonenumber" (123-5434) or Null. I want to extract area code from Phone_Number column and show it as a separate column of area code in my select query.
The query used is like this.
SELECT person_number,
COALESCE ((SELECT phone_number
FROM Primary_phone_table PPHT
WHERE PPHT.person_id = PT.person_id),
(SELECT phone_number
FROM phone_table PHT
WHERE PHT.person_id = PT.person_id)) Phone_Number
FROM Person_Table PT
Desired O/P:
Person_Number
Phone_Number
Area_Code
Why doing it in a more complex way than it should be? Why those subqueries instead of joins? Couldn't query (you posted) be rewritten to
SELECT pt.person_number,
coalesce(ppht.phone_number, pht.phone_number) phone_number
FROM person_table pt
LEFT JOIN primary_phone_table ppht ON ppht.person_id = pt.person_id
LEFT JOIN phone_table pht ON pht.person_id = pt.person_id;
I think it could, and it should. Code you wrote might raise TOO_MANY_ROWS if someone has more than a single phone number.
In order to extract area code and phone number (separated by a "minus" sign), a simple option is to use substr + instr functions combination. Current query can be used as a "source" (either as a subquery or a CTE (the WITH factoring clause)). For example:
WITH
current_query
AS
(SELECT pt.person_number,
COALESCE (ppht.phone_number, pht.phone_number) phone_number
FROM person_table pt
LEFT JOIN primary_phone_table ppht ON ppht.person_id = pt.person_id
LEFT JOIN phone_table pht ON pht.person_id = pt.person_id)
SELECT c.person_number,
SUBSTR (c.phone_number, 1, INSTR (c.phone_number, '-') - 1) area_code,
SUBSTR (c.phone_number, INSTR (c.phone_number, '-') + 1) phone_number
FROM current_query c;
With some sample data:
SQL> WITH
2 current_query (person_number, phone_number)
3 AS
4 (SELECT 1, '123-5454' FROM DUAL
5 UNION ALL
6 SELECT 2, NULL FROM DUAL)
7 SELECT c.person_number,
8 SUBSTR (c.phone_number, 1, INSTR (c.phone_number, '-') - 1) area_code,
9 SUBSTR (c.phone_number, INSTR (c.phone_number, '-') + 1) phone_number
10 FROM current_query c;
PERSON_NUMBER AREA_CODE PHONE_NUMBER
------------- ---------- ------------
1 123 5454
2
SQL>
you can use following query .
SELECT pt.person_number,
coalesce(ppht.phone_number, pht.phone_number) phone_number,
SUBSTR(coalesce(ppt.phone_number, pht.phone_number),1,regexp_instr(ppt.phone_number,'[-].*') - 1) area_code
FROM person_table pt
LEFT JOIN primary_phone_table ppt ON ppt.person_id = pt.person_id
LEFT JOIN phone_table pht ON pht.person_id = pt.person_id;

Oracle - ORA-00907: missing right parenthesis

I just can't find what is wrong here. Trying to select path to the article pictures.
ORA-00907: missing right parenthesis
select artnr, listagg(path, bildnr '.' filtyp) within group (order by bildnr) as sökväg
from kund
where knr in (select knr
from kundorder
where ordnr in (select ordnr
from orderrad
where artnr in (select artnr
from artikel
where bildnr in (select bildnr
from artikelbild))))
order by artnr;
Obvious error is in listagg (missing concatenation):
No : listagg (path, bildnr '.' filtyp)
Yes: listagg (PATH, bildnr || '.' || filtyp)
The rest should be OK (as far as syntax is concerned; can't tell whether query will (or will not) return what you want).
Also, perhaps you'd rather switch to JOINs instead of using bunch of nested subqueries, e.g.
SELECT u.artnr,
LISTAGG (u.PATH, u.bildnr || '.' || u.filtyp)
WITHIN GROUP (ORDER BY u.bildnr) AS sokvag
FROM kund u
JOIN kundorder o ON u.knr = o.knr
JOIN orderrad r ON r.ordnr = o.ordnr
JOIN artikel a ON a.artnr = r.artnr
JOIN artikelbild b ON b.bildnr = a.bildnr
ORDER BY u.artnr;
As of ORA-30496: Argument should be a constant: apparently, that's true.
Code you'd like to run:
SQL> select listagg(e.ename, e.job ||'.'|| to_char(e.deptno))
2 within group (order by null) result
3 from emp e
4 where rownum <= 3;
select listagg(e.ename, e.job ||'.'|| to_char(e.deptno))
*
ERROR at line 1:
ORA-30496: Argument should be a constant.
Let's try to fool Oracle and "prepare" the separator:
SQL> with temp as
2 (select e.ename, e.job ||'.'||to_char(e.deptno) separator
3 from emp e
4 where rownum <= 3
5 )
6 select listagg(t.ename, t.separator)
7 within group (order by null)
8 from temp t;
select listagg(t.ename, t.separator)
*
ERROR at line 6:
ORA-30496: Argument should be a constant.
Still no luck. But if a separator really is a constant (comma in my example), then it works:
SQL> select listagg(e.ename ||': ' || e.job, ', ')
2 within group (order by null) result
3 from emp e
4 where rownum <= 3;
RESULT
------------------------------------------------------------------------
ALLEN: SALESMAN, SMITH: CLERK, WARD: SALESMAN
SQL>

linking the query in the select statement

From the query i am able to return the output as expected ..
Is it possible to write the same query in the below marked quotes using select statement:
SELECT ACC.ACCOUNT_NUM AS ACCOUNT_NUMBER,
ACC.ACCOUNT_NAME AS ACCOUNT_NAME,
ADR.ADDRESS_1 AS BUILDING_TYPE,
ACC.CUSTOMER_REF AS CUSTOMER_ID,
CAT.BC AS BILL_CYCLE,
CES.EVENT_SOURCE AS TELEPHONE_NUMBER,
AAT.PACKAGE_NAME AS PROMO_PACKAGE,
PRD.PRODUCT_NAME AS SERVICES,
(SELECT COUNT (DISTINCT (EVENT_SOURCE))
FROM CUSTEVENTSOURCE CES1
WHERE CES1.CUSTOMER_REF = ACC.CUSTOMER_REF AND END_DTM IS NULL)
AS TOTAL_NUMBER,
("SELECT LISTAGG (EVENT_SOURCE, ', ')
WITHIN GROUP (ORDER BY EVENT_SOURCE)
FROM CUSTEVENTSOURCE
WHERE CUSTOMER_REF = ACC.CUSTOMER_REF AND END_DTM IS NULL")
AS ALL_IPHONE_NUMBERS,
CUS.COMPANY_NAME AS COMPANY_NAME,
ADR.ADDRESS_1
|| ' '
|| ADR.ADDRESS_2
|| ' '
|| ADR.ADDRESS_3
|| ' '
|| ADR.ADDRESS_4
|| ' '
|| ADR.ADDRESS_5
AS BILLING_ADDRESS,
(SELECT ADR.ADDRESS_1
FROM ADDRESS ADR
WHERE ADR.CUSTOMER_REF = ACC.CUSTOMER_REF
AND ADDRESS_SEQ IN
(SELECT ADDRESS_SEQ
FROM CUSTPRODUCTADDRESS CPA
WHERE CPA.CUSTOMER_REF = ADR.CUSTOMER_REF
AND PRODUCT_SEQ IN
(SELECT PRODUCT_SEQ
FROM CUSTPRODUCTSTATUS CPS
WHERE CPS.CUSTOMER_REF =
CPA.CUSTOMER_REF
AND EFFECTIVE_DTM =
(SELECT MAX (
EFFECTIVE_DTM)
FROM CUSTPRODUCTSTATUS CPS1
WHERE CPS1.CUSTOMER_REF =
CPS.
CUSTOMER_REF))))
AS INSTALLATION_ADDRESS,
(SELECT ACS.EFFECTIVE_DTM
FROM ACCOUNTSTATUS ACS
WHERE ACS.ACCOUNT_NUM = ACC.ACCOUNT_NUM
AND ACS.EFFECTIVE_DTM =
(SELECT MAX (EFFECTIVE_DTM)
FROM ACCOUNTSTATUS ACS1
WHERE ACS1.ACCOUNT_NUM = ACS.ACCOUNT_NUM
AND ACCOUNT_STATUS = 'OK'))
AS ACTIVATION_DATE,
(SELECT ACS.ACCOUNT_STATUS
FROM ACCOUNTSTATUS ACS
WHERE ACS.ACCOUNT_NUM = ACC.ACCOUNT_NUM
AND ACS.EFFECTIVE_DTM =
(SELECT MAX (EFFECTIVE_DTM)
FROM ACCOUNTSTATUS ACS1
WHERE ACS1.ACCOUNT_NUM = ACS.ACCOUNT_NUM))
AS ACCOUNT_STATUS,
(SELECT ACS.STATUS_REASON_TXT
FROM ACCOUNTSTATUS ACS
can u please help me out..I am new to sql..please
Thanks in advance..
The above needs to be changed within the "" double quotes
The output looks like:
ACCOUNT_NUMBER ACCOUNT_NAME BUILDING_TYPE CUSTOMER_ID TELEPHONE_NUMBER PROMO_PACKAGE TOTAL_NUMBER ALL_IPHONE_NUMBERS,
MTX000110 John xxxx 10002 123456 yyy 3 001-003,004,007
If the account has 3 totoal_number then in the All_iphone_numbers column if the values have sequenced numbers then it should '-' with separator otherwise it has to display the number
If I use the " " doubl quoted array..I am getting the output as comma separated values whic is incorrec result..the result should looks like "if the values have sequenced numbers then it should '-' with separator otherwise it has to display the number".
Try this: (Note: I dont have 11G R2, so I used wm_concat to test it, which is not supported, but if you have 11G R2, then use LISTAGG)
WITH TABIBITOSAN
AS (SELECT
ACCOUNT_REF,
"number",
TO_NUMBER ( "number" )
- ROW_NUMBER ( ) OVER (ORDER BY TO_NUMBER ( "number" ))
AS GRP
FROM
TBL),
DATASET1
AS (SELECT
ACCOUNT_REF,
CASE
WHEN MIN ( "number" ) = MAX ( "number" )
THEN
MIN ( "number" )
ELSE
MIN ( "number" )
|| '-'
|| MAX ( "number" )
END
AS RANGES
FROM
TABIBITOSAN
GROUP BY
ACCOUNT_REF,
GRP
ORDER BY
ACCOUNT_REF,
MIN ( "number" ))
SELECT
ACCOUNT_REF,
WM_CONCAT ( RANGES ) AS NEW_RANGES
FROM
DATASET1
GROUP BY
ACCOUNT_REF;
Results:
101 002-004,006-008,011
Using LISTAGG
SELECT
ACCOUNT_REF,
LISTAGG ( RANGES,
',' )
WITHIN GROUP (ORDER BY RANGES)
AS NEW_RANGES
FROM
DATASET1
WHERE
ACCOUNT_REF = ACC.ACCOUNT_REF
GROUP BY
ACCOUNT_REF

Query on a AS tablename in Oracle 10g

Hey all, how can i go about query off a made AS Tablename in a query of mine?
(its a long query so i have shortened it to the needed lines for this example)
SELECT
TO_CHAR(SYSDATE, 'YYYYMMDD') AS CURDATE,
TO_CHAR(A.DUE_DATE, 'YYYYMMDD') AS DUE,
UGRP.GROUP_CODE AS UGRPCODE,
A.DETAILS,
TRIM(STF.IDENTIFIER_1) || ', ' || TRIM(STF.IDENTIFIER_2) || ' ' || TRIM(STF.IDENTIFIER_3) AS STAFF,
FROM REC.CUSTOM_ATTRIBUTES E
INNER JOIN REC.SERVICE_REQUESTS SR
INNER JOIN REC.IDENTIFIERS STF ON A.ASSIGNED_STAFF_EID = STF.OWNER_EID ON E.OWNER_EID = SR.EID
WHERE (TYP.TYPE_CODE = 'SRSRTYPE')
AND (A.ASSIGNED_STAFF_EID <> 2000478)
AND STAFF = 'BARKER, BOB'
ORDER BY SR.SERVICE_REQUEST_NUM
Naturally the AND STAFF = 'BARKER, BOB" will not work for me.
My question is how can I query on that column?
Thanks!
David
Repeat the formula in your WHERE clause.
... AND TRIM(STF.IDENTIFIER_1) || ', ' || TRIM(STF.IDENTIFIER_2) || ' ' || TRIM(STF.IDENTIFIER_3) = 'BARKER, BOB' ...