Oracle: normalized fields to CSV string - sql

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.

Related

Filter Alphabets from Oracle table

I have input like :-
Table 1
Table 2
A
4
B
5
C
6
1
X
2
Y
3
Z
And Output muse be
Output
A
B
C
X
Y
Z
One method uses a union followed by a filter:
SELECT val
FROM
(
SELECT col1 AS val FROM yourTable
UNION ALL
SELECT col2 FROM yourTable
) t
WHERE REGEXP_LIKE(val, '^[A-Z]+$')
ORDER BY val;
If data really looks as you put it, a simple option is to use greatest function.
Sample data:
SQL> with test (col1, col2) as
2 (select 'A', '4' from dual union all
3 select 'B', '5' from dual union all
4 select 'C', '6' from dual union all
5 select '1', 'X' from dual union all
6 select '2', 'Y' from dual union all
7 select '3', 'Z' from dual
8 )
Query:
9 select greatest(col1, col2) result
10 from test;
RESULT
----------
A
B
C
X
Y
Z
6 rows selected.
SQL>

SQL query to find duplicates with mismatching another column

Table looks like this:
col1 | col2
A | B
A | B
D | C
D | C
E | F
E | G
what I need, is to extract col1 E.
Already tried couple variants of SELECT DISTINCT or SELECT ..., COUNT(*) with GROUP BY, but can't figure it out.
p.s. DBMS is Oracle
Such as this?
SQL> with test (col1, col2) as
2 (select 'A', 'B' from dual union all
3 select 'A', 'B' from dual union all
4 select 'D', 'C' from dual union all
5 select 'D', 'C' from dual union all
6 select 'E', 'F' from dual union all
7 select 'E', 'G' from dual
8 )
9 select col1
10 from test
11 group by col1
12 having count(distinct col2) > 1;
C
-
E
SQL>

Is there a Dataprep rolling list equivalent function in BigQuery?

I'm looking for functionality similar to this in BigQuery: https://cloud.google.com/dataprep/docs/html/ROLLINGLIST-Function_118228853
Does anyone know of a suitable function?
Below example for BigQuery Standard SQL
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'a' col1, 1 col2 UNION ALL
SELECT 'b', 2 UNION ALL
SELECT 'c', 3 UNION ALL
SELECT 'd', 4 UNION ALL
SELECT 'e', 5 UNION ALL
SELECT 'f', 6 UNION ALL
SELECT 'g', 7 UNION ALL
SELECT 'h', 8
)
SELECT *,
STRING_AGG(col1)
OVER(ORDER BY col2 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) rolling_list
FROM `project.dataset.table`
with output
Row col1 col2 rolling_list
1 a 1 a
2 b 2 a,b
3 c 3 a,b,c
4 d 4 b,c,d
5 e 5 c,d,e
6 f 6 d,e,f
7 g 7 e,f,g
8 h 8 f,g,h

Regular expression matching with Oracle

I am working on SQL Developer. I want only those records which have non-numeric data. The query I used is:
select * from TBL_NAME where regexp_like (mapping_name,'%[!0-9]%');
Strangely this is not working.
How about this? As you said, return values that are NOT numbers.
SQL> with test (col) as
2 (select 'abc123' from dual union
3 select '12345' from dual union
4 select 'abc' from dual union
5 select '($ff3' from dual union
6 select '12.345' from dual
7 )
8 select col
9 from test
10 where not regexp_like (col, '^\d+|(\.\d+)$');
COL
------
($ff3
abc
abc123
SQL>
If there are no decimal values, regular expression is even simpler: '^\d+$'
[EDIT, after sample data have been provided]
Piece of cake:
SQL> with test (col) as
2 (select 'ABC' from dual union
3 select 'BCE1' from dual union
4 select '2GHY' from dual union
5 select 'WE56S' from dual union
6 select 'TUY' from dual
7 )
8 select col
9 from test
10 where not regexp_like (col, '\d');
COL
-----
ABC
TUY
SQL>

How to convert table using SQL

I'm sorry if this is a duplicate question, but I had no idea which search keywords to use (that's why the question is vague as well)
I have a table like this
Parent_ID Parent_item Child_Item
1 A B
1 A C
2 H I
2 H J
2 H K
And I would like to have the results in the following format:
Parent_ID Parent_or_Child
1 A
1 B
1 C
2 H
2 I
2 J
2 K
How can this be done?
Thanks!
You need to unpivot the data, use UNION
select Parent_ID,Parent_item
from yourtable
Union
select Parent_ID,Child_Item
from yourtable
You need to unpivot the data, and it seems you don't want duplicates so you need to select distinct. In Oracle 11.1 or above, you can use the UNPIVOT operator - the advantage is that the base table will be read just once.
You can add an order by clause if you need it; I didn't, so the rows in the output are in arbitrary order (if you compare to your "desired output").
with
test_data ( Parent_ID, Parent_item, Child_Item ) as (
select 1, 'A', 'B' from dual union all
select 1, 'A', 'C' from dual union all
select 2, 'H', 'I' from dual union all
select 2, 'H', 'J' from dual union all
select 2, 'H', 'K' from dual
)
-- End of test data (NOT part of the query).
-- SQL query begins BELOW THIS LINE.
select distinct parent_id, parent_or_child
from test_data
unpivot (parent_or_child
for col in (parent_item as 'parent_item', child_item as 'child_item'))
;
PARENT_ID PARENT_OR_CHILD
---------- ---------------
2 I
1 A
1 B
1 C
2 H
2 J
2 K
7 rows selected.