Convert delimiter data to rows and columns - oracle
i have RAW data in Results column like below with semicolon separated.
Case ID;HPMN;VPMN;IMSI;Case Creation Time;Case Reporting Time;Case Closure Time;Last Call Time;Fraud Type;Reporting Remarks;SDR Value - Created (TAP);SDR Value - Created (NRT);SDR Value - Reported (TAP);SDR Value - Reported (NRT);SDR Value - Closed (TAP);SDR Value - Closed (NRT);SDR Value - Total (TAP);SDR Value - Total (NRT);SDR Value - Fraud Loss (TAP);SDR Value - Fraud Loss (NRT);Case Status ID;Case Status;Analyst Name - Assigned;Analyst Name - Closure;Group;Flag;7014472;NLXLT;ESPAT;204046205787443;17.05.2018 00:00;17.05.2018 05:57;;18.05.2018 06:45:09;High Usage Request ;;10.35;0; 10.35;0;0;0;20.72;0;10.37;0;512;Pending;Gloriana;Lokesh;AllRoamingGroup P1;non-hosted;7014473;OMNNT;ARETC;422030204010256;17.05.2018 00:01;17.05.2018 05:57;;15.05.2018 19:47:09;OMNNT 10MB & 50 SDRs;;51.35 ;0;51.35;0;0;0;51.35 ;0;0;0;512;Pending;Gloriana;Jordan;AllRoamingGroup P1;non-hosted;7014474;NLXLT;CZECM;204046868687429;17.05.2018 00:02;;17.05.2018 00:24;17.05.2018 15:36:23;Call third country;;0;0;0;0;0;0;.44;0;.44;0;2048;Closed Not Fraud;Gloriana;Gloriana;AllRoamingGroup P1;non-hosted;
7014475;DOMCL;PRICL;370021204427525;17.05.2018 00:03;;17.05.2018 00:26;17.05.2018 22:44:19;Call third country;;0;230.41;0;0;0;230.41;1.94;1200.07;1.94;969.66;2048;Closed Not Fraud;Gloriana;Gloriana;AllRoamingGroup P1;non-hosted;
But i need output in this way
I tried regular expression but not able to get the desired output
This will get the first 16 columns.... but you can just add extra columns as needed following the same pattern:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name ( value ) AS
SELECT 'Case ID;HPMN;VPMN;IMSI;Case Creation Time;Case Reporting Time;Case Closure Time;Last Call Time;Fraud Type;Reporting Remarks;SDR Value - Created (TAP);SDR Value - Created (NRT);SDR Value - Reported (TAP);SDR Value - Reported (NRT);SDR Value - Closed (TAP);SDR Value - Closed (NRT);SDR Value - Total (TAP);SDR Value - Total (NRT);SDR Value - Fraud Loss (TAP);SDR Value - Fraud Loss (NRT);Case Status ID;Case Status;Analyst Name - Assigned;Analyst Name - Closure;Group;Flag;7014472;NLXLT;ESPAT;204046205787443;17.05.2018 00:00;17.05.2018 05:57;;18.05.2018 06:45:09;High Usage Request ;;10.35;0; 10.35;0;0;0;20.72;0;10.37;0;512;Pending;Gloriana;Lokesh;AllRoamingGroup P1;non-hosted;7014473;OMNNT;ARETC;422030204010256;17.05.2018 00:01;17.05.2018 05:57;;15.05.2018 19:47:09;OMNNT 10MB & 50 SDRs;;51.35 ;0;51.35;0;0;0;51.35 ;0;0;0;512;Pending;Gloriana;Jordan;AllRoamingGroup P1;non-hosted;7014474;NLXLT;CZECM;204046868687429;17.05.2018 00:02;;17.05.2018 00:24;17.05.2018 15:36:23;Call third country;;0;0;0;0;0;0;.44;0;.44;0;2048;Closed Not Fraud;Gloriana;Gloriana;AllRoamingGroup P1;non-hosted; 7014475;DOMCL;PRICL;370021204427525;17.05.2018 00:03;;17.05.2018 00:26;17.05.2018 22:44:19;Call third country;;0;230.41;0;0;0;230.41;1.94;1200.07;1.94;969.66;2048;Closed Not Fraud;Gloriana;Gloriana;AllRoamingGroup P1;non-hosted;' FROM DUAL;
Query 1:
WITH data (
value,
lvl,
maxlvl,
Case_ID,
HPMN,
VPMN,
IMSI,
Case_Creation_Time,
Case_Reporting_Time,
Case_Closure_Time,
Last_Call_Time,
Fraud_Type,
Reporting_Remarks,
SDR_Value_Created_TAP,
SDR_Value_Created_NRT,
SDR_Value_Reported_TAP,
SDR_Value_Reported_NRT,
SDR_Value_Closed_TAP,
SDR_Value_Closed_NRT
) AS (
SELECT value,
1,
REGEXP_COUNT( value, '([^;]*);' ) / 26,
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 1, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 2, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 3, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 4, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 5, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 6, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 7, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 8, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 9, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 10, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 11, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 12, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 13, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 14, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 15, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, 0*26 + 16, NULL, 1 )
FROM table_name
UNION ALL
SELECT value,
lvl+1,
maxlvl,
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 1, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 2, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 3, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 4, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 5, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 6, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 7, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 8, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 9, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 10, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 11, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 12, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 13, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 14, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 15, NULL, 1 ),
REGEXP_SUBSTR( value, '([^;]*);', 1, lvl*26 + 16, NULL, 1 )
FROM data
WHERE lvl < maxlvl
)
SELECT Case_ID,
HPMN,
VPMN,
IMSI,
Case_Creation_Time,
Case_Reporting_Time,
Case_Closure_Time,
Last_Call_Time,
Fraud_Type,
Reporting_Remarks,
SDR_Value_Created_TAP,
SDR_Value_Created_NRT,
SDR_Value_Reported_TAP,
SDR_Value_Reported_NRT,
SDR_Value_Closed_TAP,
SDR_Value_Closed_NRT
FROM data
WHERE lvl > 1
Results:
| CASE_ID | HPMN | VPMN | IMSI | CASE_CREATION_TIME | CASE_REPORTING_TIME | CASE_CLOSURE_TIME | LAST_CALL_TIME | FRAUD_TYPE | REPORTING_REMARKS | SDR_VALUE_CREATED_TAP | SDR_VALUE_CREATED_NRT | SDR_VALUE_REPORTED_TAP | SDR_VALUE_REPORTED_NRT | SDR_VALUE_CLOSED_TAP | SDR_VALUE_CLOSED_NRT |
|----------|-------|-------|-----------------|--------------------|---------------------|-------------------|---------------------|----------------------|-------------------|-----------------------|-----------------------|------------------------|------------------------|----------------------|----------------------|
| 7014472 | NLXLT | ESPAT | 204046205787443 | 17.05.2018 00:00 | 17.05.2018 05:57 | (null) | 18.05.2018 06:45:09 | High Usage Request | (null) | 10.35 | 0 | 10.35 | 0 | 0 | 0 |
| 7014473 | OMNNT | ARETC | 422030204010256 | 17.05.2018 00:01 | 17.05.2018 05:57 | (null) | 15.05.2018 19:47:09 | OMNNT 10MB & 50 SDRs | (null) | 51.35 | 0 | 51.35 | 0 | 0 | 0 |
| 7014474 | NLXLT | CZECM | 204046868687429 | 17.05.2018 00:02 | (null) | 17.05.2018 00:24 | 17.05.2018 15:36:23 | Call third country | (null) | 0 | 0 | 0 | 0 | 0 | 0 |
| 7014475 | DOMCL | PRICL | 370021204427525 | 17.05.2018 00:03 | (null) | 17.05.2018 00:26 | 17.05.2018 22:44:19 | Call third country | (null) | 0 | 230.41 | 0 | 0 | 0 | 230.41 |
Query 2:
SELECT RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 1 ), ';' ) AS Case_ID,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 2 ), ';' ) AS HPMN,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 3 ), ';' ) AS VPMN,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 4 ), ';' ) AS IMSI,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 5 ), ';' ) AS Case_Creation_Time,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 6 ), ';' ) AS Case_Reporting_Time,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 7 ), ';' ) AS Case_Closure_Time,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 8 ), ';' ) AS Last_Call_Time,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 9 ), ';' ) AS Fraud_Type,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 10 ), ';' ) AS Reporting_Remarks,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 11 ), ';' ) AS SDR_Value_Created_TAP,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 12 ), ';' ) AS SDR_Value_Created_NRT,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 13 ), ';' ) AS SDR_Value_Reported_TAP,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 14 ), ';' ) AS SDR_Value_Reported_NRT,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 15 ), ';' ) AS SDR_Value_Closed_TAP,
RTRIM( REGEXP_SUBSTR( value, '.*?;', 1, l.COLUMN_VALUE*26 + 16 ), ';' ) AS SDR_Value_Closed_NRT
FROM table_name t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT LEVEL
FROM DUAL
CONNECT BY REGEXP_SUBSTR( t.value, '.*?;', 1, LEVEL*26 + 1 ) IS NOT NULL
)
AS SYS.ODCINUMBERLIST
)
) l
Results:
| CASE_ID | HPMN | VPMN | IMSI | CASE_CREATION_TIME | CASE_REPORTING_TIME | CASE_CLOSURE_TIME | LAST_CALL_TIME | FRAUD_TYPE | REPORTING_REMARKS | SDR_VALUE_CREATED_TAP | SDR_VALUE_CREATED_NRT | SDR_VALUE_REPORTED_TAP | SDR_VALUE_REPORTED_NRT | SDR_VALUE_CLOSED_TAP | SDR_VALUE_CLOSED_NRT |
|----------|-------|-------|-----------------|--------------------|---------------------|-------------------|---------------------|----------------------|-------------------|-----------------------|-----------------------|------------------------|------------------------|----------------------|----------------------|
| 7014472 | NLXLT | ESPAT | 204046205787443 | 17.05.2018 00:00 | 17.05.2018 05:57 | (null) | 18.05.2018 06:45:09 | High Usage Request | (null) | 10.35 | 0 | 10.35 | 0 | 0 | 0 |
| 7014473 | OMNNT | ARETC | 422030204010256 | 17.05.2018 00:01 | 17.05.2018 05:57 | (null) | 15.05.2018 19:47:09 | OMNNT 10MB & 50 SDRs | (null) | 51.35 | 0 | 51.35 | 0 | 0 | 0 |
| 7014474 | NLXLT | CZECM | 204046868687429 | 17.05.2018 00:02 | (null) | 17.05.2018 00:24 | 17.05.2018 15:36:23 | Call third country | (null) | 0 | 0 | 0 | 0 | 0 | 0 |
| 7014475 | DOMCL | PRICL | 370021204427525 | 17.05.2018 00:03 | (null) | 17.05.2018 00:26 | 17.05.2018 22:44:19 | Call third country | (null) | 0 | 230.41 | 0 | 0 | 0 | 230.41 |
Related
select only required text in oracle without hardcoding the character position
I have a column in database which stores data like follows {0}="[DYD666020115982-ZO]",{1}="SomeText" I want to get the 0th value ie DYD666020115982-ZO printed in output. I have tried SUBSTR({0}="[DYD666020115982-ZO]",{1}="SomeText",7,18) which gives me output, but I wanted to know is there any other way without hard coding the position.
The oldfashioned substr + instr combination works good, works fast (res_1). Regexp (res_2) along with trims (because of parenthesis) is another option: SQL> with test (col) as 2 (select '{0}="[DYD666020115982-ZO]",{1}="SomeText"' from dual) 3 select substr(col, instr(col, '[') + 1, 4 instr(col, ']') - instr(col, '[') - 1 5 ) res_1, 6 -- 7 rtrim(ltrim(regexp_substr(col, '\[.+\]'), '['), ']') res_2 8 from test; RES_1 RES_2 ------------------ ------------------ DYD666020115982-ZO DYD666020115982-ZO SQL>
You can use REGEXP_SUBSTR to match the pattern (^|,)\{0\}="(([^"]|\\")*?)"(,|$): Oracle Setup: CREATE TABLE test_data ( id, list ) AS SELECT 1, '{0}="[DYD666020115982-ZO]",{1}="SomeText"' FROM DUAL UNION ALL SELECT 2, '{1}="SomeText with a \"Quote\"",{0}="[DYD666020115982-ZO]"' FROM DUAL UNION ALL SELECT 3, '{1}="SomeText"' FROM DUAL UNION ALL SELECT 4, '{0}="[DYD666020115982-ZO-2]",{1}="SomeText",{0}="[DYD666020115982-ZO-1]"' FROM DUAL UNION ALL SELECT 5, '{1}="{0}=\"[DYD666020115982-ZO]\""' FROM DUAL; Query: SELECT REGEXP_SUBSTR( list, '(^|,)\{0\}="(([^"]|\\")*?)"(,|$)', 1, 1, NULL, 2 ) AS value FROM test_data Output: | VALUE | | :--------------------- | | [DYD666020115982-ZO] | | [DYD666020115982-ZO] | | null | | [DYD666020115982-ZO-2] | | null | or, if you want to string the leading and training characters then: SELECT SUBSTR( value, 2, LENGTH( value ) - 2 ) AS value FROM ( SELECT REGEXP_SUBSTR( list, '(^|,)\{0\}="(([^"]|\\")*?)"(,|$)', 1, 1, NULL, 2 ) AS value FROM test_data ) which outputs: | VALUE | | :------------------- | | DYD666020115982-ZO | | DYD666020115982-ZO | | null | | DYD666020115982-ZO-2 | | null | If you want to get all the values then you can use a recursive sub-query and REGEXP_SUBSTR: Query: WITH data ( id, list, key, value, idx, max_idx ) AS ( SELECT id, list, TO_NUMBER( REGEXP_SUBSTR( list, '\{(\d+)\}="(([^"]|\\")*?)"(,|$)', 1, 1, NULL, 1 ) ), REGEXP_SUBSTR( list, '\{(\d+)\}="(([^"]|\\")*?)"(,|$)', 1, 1, NULL, 2 ), 1, REGEXP_COUNT( list, '\{(\d+)\}="(([^"]|\\")*?)"(,|$)' ) FROM test_data UNION ALL SELECT id, list, TO_NUMBER( REGEXP_SUBSTR( list, '\{(\d+)\}="(([^"]|\\")*?)"(,|$)', 1, idx + 1, NULL, 1 ) ), REGEXP_SUBSTR( list, '\{(\d+)\}="(([^"]|\\")*?)"(,|$)', 1, idx + 1, NULL, 2 ), idx + 1, max_idx FROM data WHERE idx < max_idx ) SELECT id, key, value FROM data WHERE idx <= max_idx ORDER BY id, key Output: ID | KEY | VALUE -: | --: | :--------------------------- 1 | 0 | [DYD666020115982-ZO] 1 | 1 | SomeText 2 | 0 | [DYD666020115982-ZO] 2 | 1 | SomeText with a \"Quote\" 3 | 1 | SomeText 4 | 0 | [DYD666020115982-ZO-2] 4 | 0 | [DYD666020115982-ZO-1] 4 | 1 | SomeText 5 | 1 | {0}=\"[DYD666020115982-ZO]\" If you just want the values where the key is 0 then add AND key = 0 to the end of the query. db<>fiddle here
Group based on date diff without using recursive
How to convert below SQL server recursive query in vertica. I know that vertica does not support recursive query. i tried using sum() over with lag but i am still not able to acheive final expected output. with Product as ( select * from ( VALUES (1, '2018-12-25','2019-01-05' ), (1, '2019-03-01','2019-03-10' ), (1, '2019-03-15','2019-03-19' ), (1, '2019-03-22','2019-03-28' ), (1, '2019-03-30','2019-04-02' ), (1, '2019-04-10','2019-04-15' ), (1, '2019-04-18','2019-04-25' ) ) as a1 (ProductId ,ProductStartDt ,ProductEndDt) ), OrderedProduct as ( select *, ROW_NUMBER() over (order by ProductStartDt) as RowNum from Product ), DateGroupsInterim (RowNum, GroupNum, GrpStartDt, Indx) as ( select RowNum, 1, ProductEndDt,1 from OrderedProduct where RowNum=1 union all select OrderedProduct.RowNum, CASE WHEN OrderedProduct.ProductStartDt <= dateadd(day, 15, dgi.GrpStartDt) THEN dgi.GroupNum ELSE dgi.GroupNum + 1 END, CASE WHEN OrderedProduct.ProductStartDt <= dateadd(day, 15, dgi.GrpStartDt) THEN dgi.GrpStartDt ELSE OrderedProduct.ProductEndDt END, CASE WHEN OrderedProduct.ProductStartDt <= dateadd(day, 15, dgi.GrpStartDt) THEN 0 ELSE 1 END from DateGroupsInterim dgi join OrderedProduct on OrderedProduct.RowNum=dgi.RowNum+1 ) select OrderedProduct.ProductId, OrderedProduct.ProductStartDt, OrderedProduct.ProductEndDt, DateGroupsInterim.GrpStartDt, DateGroupsInterim.GroupNum, Indx from DateGroupsInterim JOIN OrderedProduct on OrderedProduct.RowNum = DateGroupsInterim.RowNum order by 2 Below is how the expected output looks like.
The operation you want to do is also called "sessionization" - which is the operation of splitting a time series into groups/ sub time series that have a certain meaning together. The way you describe it, it does not seem to be possible: The next group relies exactly on both the start of its previous group (15 min later than the start of the first row of the previous group) and the end of the previous group's last row. This needs to be a loop or a recursion, which is not offered by Vertica. I managed to join the table with itself and get a session id for consecutive rows within 15 minutes. But, as of now, they're overlapping, and I found no way to determine which group I want to keep... Like so: WITH product(productid ,productstartdt ,productenddt) AS ( SELECT 1, DATE '2018-12-25',DATE '2019-01-05' UNION ALL SELECT 1, DATE '2019-03-01',DATE '2019-03-10' UNION ALL SELECT 1, DATE '2019-03-15',DATE '2019-03-19' UNION ALL SELECT 1, DATE '2019-03-22',DATE '2019-03-28' UNION ALL SELECT 1, DATE '2019-03-30',DATE '2019-04-02' UNION ALL SELECT 1, DATE '2019-04-10',DATE '2019-04-15' UNION ALL SELECT 1, DATE '2019-04-18',DATE '2019-04-25' ) , groups AS ( SELECT a.productstartdt AS in_productstartdt , b.* , CONDITIONAL_CHANGE_EVENT(a.productstartdt) OVER(PARTITION BY a.productid ORDER BY a.productstartdt) AS grp FROM product a LEFT JOIN product b ON a.productid = b.productid AND a.productstartdt <= b.productstartdt AND (a.productstartdt=b.productstartdt OR b.productstartdt <= a.productenddt + 15) ) SELECT * FROM groups; -- out in_productstartdt | productid | productstartdt | productenddt | grp -- out -------------------+-----------+----------------+--------------+----- -- out 2018-12-25 | 1 | 2018-12-25 | 2019-01-05 | 0 -- out 2019-03-01 | 1 | 2019-03-01 | 2019-03-10 | 1 -- out 2019-03-01 | 1 | 2019-03-22 | 2019-03-28 | 1 -- out 2019-03-01 | 1 | 2019-03-15 | 2019-03-19 | 1 -- out 2019-03-15 | 1 | 2019-03-15 | 2019-03-19 | 2 -- out 2019-03-15 | 1 | 2019-03-22 | 2019-03-28 | 2 -- out 2019-03-15 | 1 | 2019-03-30 | 2019-04-02 | 2 -- out 2019-03-22 | 1 | 2019-03-22 | 2019-03-28 | 3 -- out 2019-03-22 | 1 | 2019-03-30 | 2019-04-02 | 3 -- out 2019-03-22 | 1 | 2019-04-10 | 2019-04-15 | 3 -- out 2019-03-30 | 1 | 2019-04-10 | 2019-04-15 | 4 -- out 2019-03-30 | 1 | 2019-03-30 | 2019-04-02 | 4 -- out 2019-04-10 | 1 | 2019-04-10 | 2019-04-15 | 5 -- out 2019-04-10 | 1 | 2019-04-18 | 2019-04-25 | 5 -- out 2019-04-18 | 1 | 2019-04-18 | 2019-04-25 | 6 -- out (15 rows) -- out -- out Time: First fetch (15 rows): 35.454 ms. All rows formatted: 35.503 ms What is the next difficulty is how to get rid of grp-s 2, 3, and 5 ....
Sets From a Single Table, Grouped By a Column
I have a table: +-------+-------+----------+ | GROUP | State | Priority | +-------+-------+----------+ | 1 | MI | 1 | | 1 | IA | 2 | | 1 | CA | 3 | | 1 | ND | 4 | | 1 | AZ | 5 | | 2 | IA | 2 | | 2 | NJ | 1 | | 2 | NH | 3 | And so on... How do I write a query that makes all the sets of the states by group, in priority order? Like so: +-------+--------------------+ | GROUP | SET | +-------+--------------------+ | 1 | MI | | 1 | MI, IA | | 1 | MI, IA, CA | | 1 | MI, IA, CA, ND | | 1 | MI, IA, CA, ND, AZ | | 2 | NJ | | 2 | NJ, IA | | 2 | NJ, IA, NH | +-------+--------------------+ This is similar to my question here and I've tried to modify that solution but, I'm just a forty watt bulb and it's a sixty watt problem...
This problem actually looks simpler than the answer to the question you linked, which is an excellent solution to that problem. Nevertheless, this uses the same hierarchical queries, with connect by If it is the case that priority is always a continuous sequence of numbers, this will work SELECT t.grp, level, ltrim(SYS_CONNECT_BY_PATH(state,','),',') as "set" from t start with priority = 1 connect by priority = prior priority + 1 and grp = prior grp However, if that's not always true, we would require row_number() to define the sequence based on the order of priority ( which need not be consecutive integer) with t2 AS ( select t.*, row_number() over ( partition by grp order by priority) as rn from t ) SELECT t2.grp, ltrim(SYS_CONNECT_BY_PATH(state,','),',') as "set" from t2 start with priority = 1 connect by rn = prior rn + 1 and grp = prior grp DEMO
I realize this has already been answered, but I wanted to see if I could do this using ANSI standard syntax. "connect by" is an Oracle only feature, the following will work on multiple databases: WITH -- ASET is just setting up the sample dataset aset AS (SELECT 1 AS grp, 'MI' AS state, 1 AS priority FROM DUAL UNION ALL SELECT 1 AS grp, 'IA', 2 FROM DUAL UNION ALL SELECT 1 AS grp, 'CA', 3 FROM DUAL UNION ALL SELECT 1 AS grp, 'ND', 4 FROM DUAL UNION ALL SELECT 1 AS grp, 'AZ', 5 FROM DUAL UNION ALL SELECT 2 AS grp, 'IA', 2 FROM DUAL UNION ALL SELECT 2 AS grp, 'NJ', 1 FROM DUAL UNION ALL SELECT 2 AS grp, 'NH', 3 FROM DUAL), bset AS -- In BSET we convert the ASET records into comma separated values ( SELECT grp, LISTAGG( state, ',' ) WITHIN GROUP (ORDER BY priority) AS set1 FROM aset GROUP BY grp), cset ( grp , set1 , set2 , pos ) AS -- CSET breaks our comma separated values up into multiple rows -- Each row adding the next CSV value (SELECT grp AS grp , set1 AS set1 , SUBSTR( set1 || ',', 1, INSTR( set1 || ',', ',' ) - 1 ) AS set2 , 1 AS pos FROM bset UNION ALL SELECT grp AS grp , set1 AS set1 , SUBSTR( set1 || ',' , 1 , INSTR( set1 || ',' , ',' , 1 , pos + 1 ) - 1 ) AS set2 , pos + 1 AS pos FROM cset WHERE INSTR( set1 || ',' , ',' , 1 , pos + 1 ) > 0) SELECT grp, set2 FROM cset ORDER BY grp, pos;
Oracle: How to use pivot muilti column?
I want Pivot multi column. What use oracle pivot table? SQL: SELECT * FROM ( SELECT * FROM IRO_SIM A WHERE A.COM_CODE = 'AAQ' AND A.PCODE = 'AKIOP' ) PIVOT ( LISTAGG(SIMTYPE,',') WITHIN GROUP (ORDER BY SIMTYPE) FOR SIMTYPE IN ('H','V') ) Sample Data: COM_CODE | PCODE | L_VALUE | A_SIM | AMT_SIM | SIMTYPE A | AKIOP | 1700 | TOTAL | 50 | H A | AKIOP | 500 | EACH | 100 | V A | BHUIO | 200 | TOTAL | 500 | H A | BHUIO | 600 | TOTAL | 400 | V i need Result: COM_CODE | PCODE | H_VALUE | H_ASIM | H_AMTSIM | V_VALUE | V_ASIM | V_AMTSIM A | AKIOP | 1700 | TOTAL | 50 | 500 | EACH | 100 A | BHUIO | 200 | TOTAL | 500 | 600 | TOTAL | 400 thanks advance :)
Just list the multiple columns. Every expression in your PIVOT clause will be matched with every value in the FOR clause. So, what you want is this: SELECT * FROM d PIVOT ( sum(l_value) as value, max(a_sim) as asim, sum(amt_sim) as amtsim FOR simtype in ('H' AS "H", 'V' AS "V") ) With data... with d as ( SELECT 'A' com_code, 'AKIOP' pcode, 1700 l_value, 'TOTAL' a_sim, 50 amt_sim, 'H' simtype FROM DUAL UNION ALL SELECT 'A' com_code, 'AKIOP' pcode, 500 l_value, 'EACH' a_sim, 100 amt_sim, 'V' simtype FROM DUAL UNION ALL SELECT 'A' com_code, 'BHUIO' pcode, 200 l_value, 'TOTAL' a_sim, 500 amt_sim, 'H' simtype FROM DUAL UNION ALL SELECT 'A' com_code, 'BHUIO' pcode, 600 l_value, 'TOTAL' a_sim, 400 amt_sim, 'V' simtype FROM DUAL) SELECT * FROM d PIVOT ( sum(l_value) as value, max(a_sim) as asim, sum(amt_sim) as amtsim FOR simtype in ('H' AS "H", 'V' AS "V") )
Oracle 11g hierarchical query needs some inherited data
table looks kind of like: create table taco ( taco_id int primary key not null, taco_name varchar(255), taco_prntid int, meat_id int, meat_inht char(1) -- inherit meat ) data looks like: insert into taco values (1, '1', null, 1, 'N'); insert into taco values (2, '1.1', 1, null, 'Y'); insert into taco values (3, '1.1.1', 2, null, 'N'); insert into taco values (4, '1.2', 1, 2, 'N'); insert into taco values (5, '1.2.1', 4, null, 'Y'); insert into taco values (6, '1.1.2', 2, null, 'Y'); or... - 1 has a meat_id=1 - 1.1 has a meat_id=1 because it inherits from its parent via taco_prntid=1 - 1.1.1 has a meat_id of null because it does NOT inherit from its parent - 1.2 has a meat_id=2 and it does not inherit from its parent - 1.2.1 has a meat_id=2 because it does inherit from its parent via taco_prntid=4 - 1.1.2 has a meat_id=1 because it does inherit from its parent via taco_prntid=2 Now... how in the world do I query what the meat_id is for each taco_id? What is below did work until I realized that I wasn't using the inheritance flag and some of my data was messing up. select x.taco_id, x.taco_name, to_number(substr(meat_id,instr(rtrim(meat_id), ' ', -1)+1)) as meat_id from ( select taco_id, taco_name, level-1 "level", sys_connect_by_path(meat_id, ' ') meat_id from taco start with taco_prntid is null connect by prior taco_id = taco_prntid ) x I can post some failed attempts to modify my query above but they're rather embarrassing failures. I haven't worked with hierarchical queries at all before beyond the basics so I'm hoping there is some keyword or concept I'm not aware I should be searching for. I posted an answer myself down at the bottom to show what I ended up with ultimately. I'm leaving the other answer as accepted because they were able to make the data more clear for me and without it, I wouldn't have gotten anywhere.
Your inner query is correct. All you need is to pick only the rightmost number from the meat_id column of inner query, when flag is Y. I have used REGEXP_SUBSTR function to get the rightmost number and CASE statement to check the flag. SQL Fiddle Query 1: select taco_id, taco_name, taco_prntid, case meat_inht when 'N' then meat_id when 'Y' then to_number(regexp_substr(meat_id2,'\d+\s*$')) end meat_id, meat_inht from ( select taco_id, taco_name, taco_prntid, meat_id, meat_inht, level-1 "level", sys_connect_by_path(meat_id, ' ') meat_id2 from taco start with taco_prntid is null connect by prior taco_id = taco_prntid ) order by 1 Results: | TACO_ID | TACO_NAME | TACO_PRNTID | MEAT_ID | MEAT_INHT | |---------|-----------|-------------|---------|-----------| | 1 | 1 | (null) | 1 | N | | 2 | 1.1 | 1 | 1 | Y | | 3 | 1.1.1 | 2 | (null) | N | | 4 | 1.2 | 1 | 2 | N | | 5 | 1.2.1 | 4 | 2 | Y | | 6 | 1.1.2 | 2 | 1 | Y | Query 2: select taco_id, taco_name, taco_prntid, meat_id, meat_inht, level-1 "level", sys_connect_by_path(meat_id, ' ') meat_id2 from taco start with taco_prntid is null connect by prior taco_id = taco_prntid Results: | TACO_ID | TACO_NAME | TACO_PRNTID | MEAT_ID | MEAT_INHT | LEVEL | MEAT_ID2 | |---------|-----------|-------------|---------|-----------|-------|----------| | 1 | 1 | (null) | 1 | N | 0 | 1 | | 2 | 1.1 | 1 | (null) | Y | 1 | 1 | | 3 | 1.1.1 | 2 | (null) | N | 2 | 1 | | 6 | 1.1.2 | 2 | (null) | Y | 2 | 1 | | 4 | 1.2 | 1 | 2 | N | 1 | 1 2 | | 5 | 1.2.1 | 4 | (null) | Y | 2 | 1 2 |
This is what I've ended up with so far... after applying the logic in the accepted answer. I added a few more things so that I can join the result up against my meat table. the upper case could be optimized a little bit but I am so over this part of the query so.... it's going to have to stay for now. select x.taco_id, x.taco_name, x.taco_prntname, meat_id ,case when to_number(regexp_substr(meat_id,'\d+\s*$'))=0 then null else to_number(regexp_substr(meat_id,'\d+\s*$')) end as meat_id from ( select taco_id, taco_name, taco_prntname, level-1 "level", sys_connect_by_path( case when meat_inht='N' then nvl(to_char(meat_id),'0') else '' end ,' ') meat_id from taco join jobdtl on jobdtl.jobdtl_id=taco.jobdtl_id start with taco_prntid is null connect by prior taco_id = taco_prntid ) x (do you ever wonder, when you read questions like this, what the real schema is? obviously I am not working on a taco project. or does it even matter as long as the general relationships and concept is preserved?)