Oracle rows To Column - sql

Old Result
Column_Name
A
B
C
D
New Required Result
Column_Name
'A', 'B', 'C', 'D'
Restrictions, (Count is unknown. Could be A, B, C or A, B, C, D, E and so on.

Considering your question literally, you have a query returning a single column with a variable number of rows, say
select 'A' column_name from dual union all
select 'B' column_name from dual union all
select 'C' column_name from dual union all
select 'D' column_name from dual
and you need to have the result in a single row with a single column containing the concatenation of the values returned by the original query, wrapped by ''; in your example, you need:
Column_Name
'A', 'B', 'C', 'D'
If this is correct, you may simply need listagg:
select listagg('''' || column_name || '''', ', ') within group ( order by column_name)
from (
select 'A' column_name from dual union all
select 'B' column_name from dual union all
select 'C' column_name from dual union all
select 'D' column_name from dual
) yourQuery

If you are looking to make a list of all the values in a certain column behind each other you can use LISTAGG.
For example:
SELECT LISTAGG(Column_Name, ', ') WITHIN GROUP (ORDER BY Column_Name) "Column_Listing"
FROM TableA;

Related

Grouping multiple data in oracle sql

i have this table in my oracle db
enter image description here
is there some way I can perform the grouping in SQL? so that the returned data is something like
enter image description here
Thank you
In later versions of Oracle you can use:
SELECT product_id,
LISTAGG(DISTINCT qc, ',') WITHIN GROUP (ORDER BY qc) AS qc,
LISTAGG(DISTINCT packing, ',') WITHIN GROUP (ORDER BY packing)
AS packing,
LISTAGG(DISTINCT delivering, ',') WITHIN GROUP (ORDER BY delivering)
AS delivering
FROM table_name
GROUP BY product_id
However, in Oracle 11, LISTAGG does not support the DISTINCT keyword and you would either need to pre-process the input to remove duplicates or to post-process the aggregated string:
SELECT product_id,
REPLACE(
TRIM(
BOTH ',' FROM
REGEXP_REPLACE(
',' || LISTAGG(qc, ',,') WITHIN GROUP (ORDER BY qc) || ',',
'(,.*?,)\1+',
'\1'
)
),
',,',
','
)AS qc,
REPLACE(
TRIM(
BOTH ',' FROM
REGEXP_REPLACE(
',' || LISTAGG(packing, ',,') WITHIN GROUP (ORDER BY packing) || ',',
'(,.*?,)\1+',
'\1'
)
),
',,',
','
)AS packing,
REPLACE(
TRIM(
BOTH ',' FROM
REGEXP_REPLACE(
',' || LISTAGG(delivering, ',,') WITHIN GROUP (ORDER BY delivering) || ',',
'(,.*?,)\1+',
'\1'
)
),
',,',
','
)AS delivering
FROM table_name
GROUP BY product_id
Which, for the sample data:
CREATE TABLE table_name ( product_id, qc, packing, delivering ) AS
SELECT 1, 'A', 'A', 'C' FROM DUAL UNION ALL
SELECT 1, 'A', 'B', 'C' FROM DUAL UNION ALL
SELECT 2, 'A', 'C', 'C' FROM DUAL UNION ALL
SELECT 3, 'A', 'B', 'D' FROM DUAL UNION ALL
SELECT 3, 'A', 'D', 'D' FROM DUAL;
Both output (for compliant versions):
PRODUCT_ID
QC
PACKING
DELIVERING
1
A
A,B
C
2
A
C
C
3
A
B,D
D
fiddle

Oracle dynamic query (return or select) result as table

How can I show the result of running a dynamic query as a table in the output?
I want to show the result of the following query as a table in the output.
my table :
create table myTable(ROW_NAME varchar(10),COLUMN_NAME varchar(10),COLUMN_NAME_VALUE varchar(10));
table data :
insert into myTable (ROW_NAME,COLUMN_NAME,COLUMN_NAME_VALUE)
select 'ROW1','COL1','R1C1' from dual
union all select 'ROW1','COL2','R1C2' from dual
union all select 'ROW1','COL3','R1C3' from dual
union all select 'ROW2','COL1','R2C1' from dual
union all select 'ROW2','COL2','R2C2' from dual
union all select 'ROW2','COL3','R2C3' from dual
union all select 'ROW3','COL1','R3C1' from dual
union all select 'ROW3','COL2','R3C3' from dual
union all select 'ROW3','COL3','R3C3' from dual
my dynamic query :
DECLARE
mycols VARCHAR2(1000);
sqlCommand varchar2(1000);
TYPE PivotCurTyp IS REF CURSOR;
pivot_cv PivotCurTyp;
type pivotted is record (row_name myTable.row_name%type, col1 myTable.column_name_value%type, col2 myTable.column_name_value%type, col3 myTable.column_name_value%type);
piv_rec pivotted;
BEGIN
select (select LISTAGG('''' || COLUMN_NAME || '''', ',') from myTable group by ROW_NAME FETCH FIRST 1 ROWS ONLY) into mycols from dual;
select Concat('select * from myTable pivot ( max (COLUMN_NAME_VALUE) for COLUMN_NAME in (',Concat(mycols,')) ORDER BY ROW_NAME')) into sqlCommand from dual;
DBMS_OUTPUT.PUT_LINE(sqlCommand);
OPEN pivot_cv FOR sqlCommand;
LOOP
FETCH pivot_cv INTO piv_rec;
EXIT WHEN pivot_cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('ROW_NAME: ' || piv_rec.ROW_NAME || ' COL1: ' ||
piv_rec.COL1 || ' COL2: ' || piv_rec.COL2 || ' COL3: ' || piv_rec.COL3);
END LOOP;
CLOSE pivot_cv;
END;
/
demo in db<>fiddle
Thanks for any help
Maybe I misunderstood, I guess what you want is this?
select 'ROW_NAME ' || t1.row_name || ' ' || listagg(t1.column_name || ': ' || t1.column_name_value, ' ')
within group(order by t1.column_name)
from myTable t1
group by t1.row_name
order by t1.row_name

Count number of null values for every column on a table

I would like to calculate, for each column in a table, the percent of rows that are null.
For one column, I was using:
SELECT ((SELECT COUNT(Col1)
FROM Table1)
/
(SELECT COUNT(*)
FROM Table1)) AS Table1Stats
Works great and is fast.
However, I want to do this for all ~50 columns of the table, and my environment does not allow me to use dynamic SQL.
Any recommendations? I am using snowflake to connect to AWS, but as an end user I am using the snowflake browser interface.
You can combine this as:
SELECT COUNT(Col1) * 1.0 / COUNT(*)
FROM Table1;
Or, if you prefer:
SELECT AVG( (Col1 IS NOT NULL)::INT )
FROM Table1;
You can use a mix of object_construct() and flatten() to move the column names into rows. Then do the math for the values missing:
create or replace temp table many_cols as
select 1 a, 2 b, 3 c, 4 d
union all select 1, null, 3, 4
union all select 8, 8, null, null
union all select 8, 8, 7, null
union all select null, null, null, null;
select key column_name
, 1-count(*)/(select count(*) from many_cols) ratio_null
from (
select object_construct(a.*) x
from many_cols a
), lateral flatten(x)
group by key
;
You can do this using a SQL generator if you don't mind copying the text and running it once it's done.
-- SQL generator option:
select 'select' || listagg(' ((select count(' || COLUMN_NAME || ') from "SNOWFLAKE_SAMPLE_DATA"."TPCH_SF10000"."ORDERS") / ' ||
'(select count(*) from "SNOWFLAKE_SAMPLE_DATA"."TPCH_SF10000"."ORDERS")) as ' || COLUMN_NAME, ',') as SQL_STATEMENT
from "SNOWFLAKE_SAMPLE_DATA"."INFORMATION_SCHEMA"."COLUMNS"
where TABLE_CATALOG = 'SNOWFLAKE_SAMPLE_DATA' and TABLE_SCHEMA = 'TPCH_SF10000' and TABLE_NAME = 'ORDERS'
;
If the copy and paste is not plausible because you need to script it, you can use the results of the SQL generator in a stored procedure I wrote to execute a single line of dynamic SQL:
call run_dynamic_sql(
select 'select' || listagg(' ((select count(' || COLUMN_NAME || ') from "SNOWFLAKE_SAMPLE_DATA"."TPCH_SF10000"."ORDERS") / ' ||
'(select count(*) from "SNOWFLAKE_SAMPLE_DATA"."TPCH_SF10000"."ORDERS")) as ' || COLUMN_NAME, ',') as SQL_STATEMENT
from "SNOWFLAKE_SAMPLE_DATA"."INFORMATION_SCHEMA"."COLUMNS"
where TABLE_CATALOG = 'SNOWFLAKE_SAMPLE_DATA' and TABLE_SCHEMA = 'TPCH_SF10000' and TABLE_NAME = 'ORDERS'
);
If you want the stored procedure, until it's published on Snowflake's blog it's available here: https://snowflake.pavlik.us/index.php/2021/01/22/running-dynamic-sql-in-snowflake/

Cross Join query in Oracle

I am trying to refractor a query that has in its Select concatenation of five fields, thus
SELECT
Id
'-'
Field_2
'-'
Field_3
'-'
Field_4
AS id
FROM some_table
Example result would be something like this
Id
1-a-b-c-d
2-e-f-g-h
#null#
#null#
My problem is whilst this query works, some or all of these fields could be null. It has been suggested that a cross join could be to allow a display of null when all or any of these fields are null. Unfortunately, I am not sure how to do this. The cross join has been suggested for performance due to the large number of rows.
Can someone please show me how
You don't give a lot of detail but I expect what you want is the following.
SELECT COALESCE(Id,'') || '-' ||
COALESCE(Field_2,'') || '-' ||
COALESCE(Field_3,'') || '-' ||
COALESCE(Field_4,'')
AS id
FROM some_table
try this
select nvl(concat(concat(concat(concat(a,b),c),d),e),'NULL') from some_table
when any of the fields we show the key as null with the word null
What could be joined here? Use simple case:
with sample_data(id, field1, field2, field3, field4) as (
select 1, 'a', 'b', 'c', 'd' from dual union all
select 2, 'e', 'f', 'g', 'h' from dual union all
select 3, 'p', 'q', null, 's' from dual union all
select 4, null, 'x', 'y', 'z' from dual )
select case when id is null or field1 is null or field2 is null or field3 is null or field4 is null
then '#null#'
else id || '-' || field1 || '-' || field2 || '-' || field3 || '-' || field4
end as id
from sample_data
Result:
ID
---------
1-a-b-c-d
2-e-f-g-h
#null#
#null#

Concatenate Character

I want to add a character to order_id column. The table below shows what I intend to achieve:
Add_field Order_id New_column
0 32639 032639
0 37378 037378
The result I want to achieve for each row is stored in New_column.
You can use below Sql query for concat column values in result
SELECT CONCAT(column1, ' ', column2) as columnName
FROM tableName
Here (column1, ' ', column2) you can change ' ' according your requirement.
Try:
select '0' || TO_CHAR(column1)
from yourTable
Example:
You can try (table indipendent):
select '0' || TO_CHAR(rownum)
from dual
union
select '0' || TO_CHAR(3)
from dual
union
select '0' || TO_CHAR('4')
from dual;
output will be:
01
03
04