Getting missing comma error when using Pivot function on a table - sql

I am creating a simple pivot but I get the ORA-00917: missing comma error on the line where the pivot function exists (third line). Please help.
Not sure what else to try as the syntax seems to be correct as I am new to the pivot function.
SELECT venue, notional
FROM ABC
pivot (sum(notional) FOR (venue) IN ('A' as A1 , 'B' as B1));
The expected result would be A1 and B1 showing their respective notionals.

You do not need a sub-query. The columns venue and notional in the ABC table have been pivoted and no longer exist in the output result set so the SELECT clause will not find those columns.
Instead SELECT the a1 and b1 columns you have pivoted:
Test Data:
CREATE TABLE abc ( id, venue, notional ) AS
SELECT 1, 'A', 1 FROM DUAL UNION ALL
SELECT 1, 'A', 2 FROM DUAL UNION ALL
SELECT 1, 'A', 3 FROM DUAL UNION ALL
SELECT 1, 'B', 1 FROM DUAL UNION ALL
SELECT 1, 'B', 2 FROM DUAL UNION ALL
SELECT 2, 'B', 3 FROM DUAL;
Query:
SELECT id, a1, b1 -- you can't use venue or notional here as they've been pivoted.
FROM ABC
pivot (sum(notional) FOR (venue) IN ('A' as A1 , 'B' as B1));
Output:
ID | A1 | B1
-: | ---: | -:
1 | 6 | 3
2 | null | 3
db<>fiddle here

It seems you miss the sub-query before PIVOT function -
SELECT *
FROM (SELECT venue, notional
FROM ABC
)
PIVOT (
SUM(notional) FOR (venue) IN ('A' as A1 , 'B' as B1)
);

Related

How can I count the total no of rows which is not containing some value in array field? It should include null values as well

| names |
| -----------------------------------|
| null |
| null |
| [{name:'test'},{name:'test1'}] |
| [{name:'test'},{name:'test1'}] |
| [{name:'test1'},{name:'test2'}] |
I want to count the no of rows which does not have the value 'test' in the name key.
Here it should give answer as 3 (Row no 1, 2 and 5th row) because all these row do not contain the value 'test'.
Use below approach
select count(*)
from your_table
where 0 = ifnull(array_length(regexp_extract_all(names, r"\b(name:'test')")), 0)
you can test it with below data (that resemble whatever you presented in your question)
with your_table as (
select null names union all
select null union all
select "[{name:'test'},{name:'test1'}]" union all
select "[{name:'test'},{name:'test1'}]" union all
select "[{name:'test1'},{name:'test2'}]"
)
with output
Below approach will work,
with your_table as (
select null names union all
select null union all
select [('name','test'),('name','test1')] union all
select [('name','test'),('name','test1')] union all
select [('name','test1'),('name','test2')]
)
SELECT COUNT(*) as count FROM your_table
WHERE NOT EXISTS (
SELECT 1
FROM UNNEST(your_table.names) AS names
WHERE names IN (('name','test'))
)

unpivot with a flag in Oracle

I have this table structure
ID,SUPPLIER_GROUP1,SUPPLIER1,SUPPLIER_GROUP2,SUPPLIER2.
i want to unpivot and get
ID,SUPPLIER_GROUP,SUPPLIER,TYPE
so each supplier_group and supplier values come to the appropriate column and in TYPE column will be either 1 or 2 to see if the SUPPLIER_GROUP and SUPPLIER value was supplier1 or supplier2 .
Use UNPIVOT with multiple column groups:
SELECT *
FROM table_name
UNPIVOT (
(supplier_group, supplier) FOR type IN (
(supplier_group1, supplier1) AS 1,
(supplier_group2, supplier2) AS 2
)
);
Which, for the sample data:
CREATE TABLE table_name (ID,SUPPLIER_GROUP1,SUPPLIER1,SUPPLIER_GROUP2,SUPPLIER2) AS
SELECT 1, 'sg1.1', 's1.1', 'sg2.1', 's2.1' FROM DUAL UNION ALL
SELECT 2, 'sg1.2', 's1.2', 'sg2.2', 's2.2' FROM DUAL UNION ALL
SELECT 3, 'sg1.3', 's1.3', 'sg2.3', 's2.3' FROM DUAL
Outputs:
ID
TYPE
SUPPLIER_GROUP
SUPPLIER
1
1
sg1.1
s1.1
1
2
sg2.1
s2.1
2
1
sg1.2
s1.2
2
2
sg2.2
s2.2
3
1
sg1.3
s1.3
3
2
sg2.3
s2.3
db<>fiddle here

Removing first 'G' character of entire column values in table if it is starting from 'G'

I wanted to remove first 'G' character of full column values of table only if it exist.
I have tried the substr function to remove first char but it will remove the first char even if it is not 'G'. I only wanted to remove first char of entire column values if it is 'G'.
For example in myTable the column values are as follows:
G12345
332157
G54337
G54332
534535
Expected result is as follows:
12345
332157
54337
54332
534535
Wanted to write update query to update the entire column value.
Based on your description, you can use regexp_replace():
select regexp_replace('G12345', 'G', '', 1, 1)
If you only want to remove a 'G' at the beginning of the string, you can use '^G' for the pattern.
Based on your data, you can just use replace():
select replace('G12345', 'G', '')
This removes all 'G's. But your data only seems to have one.
For an update you would just include the logic as an update:
update t
set col = replace(col, 'G', '')
where col like '%G%';
Or whichever of the above functions is what you really want to do.
You want to update the rows where the value starts with a 'G', so use a WHERE clause:
update mytable
set value = substr(value, 2)
where value like 'G%';
As you want to replace only the first G, then
SQL> with test (col) as
2 (select 'G12345' from dual union all
3 select '332157' from dual union all
4 select '11G222' from dual
5 )
6 select col,
7 substr(col, case when substr(col, 1, 1) = 'G' then 2 else 1 end) result
8 from test;
COL RESULT
------ ------
G12345 12345
332157 332157
11G222 11G222
SQL>
You can use:
SELECT CASE WHEN value LIKE 'G%' THEN SUBSTR( value, 2 ) ELSE value END
AS value_without_g
FROM myTable
Which, from the sample data:
CREATE TABLE myTable ( value ) AS
SELECT 'G12345' FROM DUAL UNION ALL
SELECT '332157' FROM DUAL UNION ALL
SELECT 'G54337' FROM DUAL UNION ALL
SELECT 'G54332' FROM DUAL UNION ALL
SELECT '534535' FROM DUAL;
Outputs:
| VALUE_WITHOUT_G |
| :-------------- |
| 12345 |
| 332157 |
| 54337 |
| 54332 |
| 534535 |
db<>fiddle here

Oracle Alpha-Numeric column sorting

I am working on to Sort the Revision column of an Oracle DB table in the asc order as per below.
At first the numeric revisions to be sorted (1,2,3,…).
Thereafter Alpha-Numeric to be sorted as following: A, B, B1, C, C1, C2,…,Y, Y2, Y3, Z, AA, AB,..,DA, …ZZ, etc.
Row_Number() in the SELECT statement to be filled with 1,2,3… for each document# (ABC, XYZ) after revision sorting out.
See the uploaded image for the required table.
I tried with SUBSTR , Order by, etc but failed to sort out as per above requirement.
Can someone help me on this ? Thanks!
As I understand your question, you want to put last revisions that contain only two characters and no digits.
You can use a conditional sort:
select
t.*,
row_number() over(
partition by doc#
order by
case when regexp_like(revision, '^\w\d?$') then 0 else 1 end,
revision
) rn
from t
order by doc#, rn
The regular expression describes a string starting with an alphanumeric character, optionally followed by a digit: these revisions should come first.
Demo on DB Fiddle:
with t as (
select 'ABC' doc#, '1' revision from dual
union all select 'ABC', '2' from dual
union all select 'ABC', '3' from dual
union all select 'ABC', 'A' from dual
union all select 'ABC', 'B' from dual
union all select 'ABC', 'B1' from dual
union all select 'ABC', 'C' from dual
union all select 'ABC', 'C1' from dual
union all select 'ABC', 'D' from dual
union all select 'ABC', 'AA' from dual
union all select 'ABC', 'AB' from dual
union all select 'ABC', 'BA' from dual
union all select 'ABC', 'DA' from dual
)
select
t.*,
row_number() over(
partition by doc#
order by
case when regexp_like(revision, '^\w\d?$') then 0 else 1 end,
revision
) rn
from t
order by doc#, rn
DOC# | REVISION | RN
:--- | :------- | -:
ABC | 1 | 1
ABC | 2 | 2
ABC | 3 | 3
ABC | A | 4
ABC | B | 5
ABC | B1 | 6
ABC | C | 7
ABC | C1 | 8
ABC | D | 9
ABC | AA | 10
ABC | AB | 11
ABC | BA | 12
ABC | DA | 13
There is well known old method: rpad(col, max-length, '0')
For example rpad(col, max(length(col)) over(), '0'

Oracle: normalized fields to CSV string

I have some one-many normalized data that looks like this.
a | x
a | y
a | z
b | i
b | j
b | k
What query will return the data such that the "many" side is represented as a CSV string?
a | x,y,z
b | i,j,k
Mark,
If you are on version 11gR2, and who isn't :-), then you can use listagg
SQL> create table t (col1,col2)
2 as
3 select 'a', 'x' from dual union all
4 select 'a', 'y' from dual union all
5 select 'a', 'z' from dual union all
6 select 'b', 'i' from dual union all
7 select 'b', 'j' from dual union all
8 select 'b', 'k' from dual
9 /
Tabel is aangemaakt.
SQL> select col1
2 , listagg(col2,',') within group (order by col2) col2s
3 from t
4 group by col1
5 /
COL1 COL2S
----- ----------
a x,y,z
b i,j,k
2 rijen zijn geselecteerd.
If your version is not 11gR2, but higher than 10gR1, then I recommend using the model clause for this, as written here: http://rwijk.blogspot.com/2008/05/string-aggregation-with-model-clause.html
If lower than 10, then you can see several techniques in rexem's link to the oracle-base page, or in the link to the OTN-thread in the blogpost mentioned above.
Regards,
Rob.