Select distinct multiple columns with one result column in Redshift - amazon-redshift

I would like execute below in Redshift. It can be handled in Postgrsql using unnest but not working in Redshift
Actually I have rows like
id col_a col_b col_c
1 ABD CDE XYZ
2 CDE null null
3 ABD null null
3 FGH LMN null
And I expect as a result
ABC
ABD
CDE
FGH
LMN
XYZ

With UNION for each of the columns, to get the distinct values:
select col_a as col from tablename
where col_a is not null
union
select col_b from tablename
where col_b is not null
union
select col_c from tablename
where col_c is not null
order by col

Related

Concatenate the result of a query into a variable in PostgreSQL

Is it possible to concatenate the result of a query into a variable in postgresql?
Something like this in MSSQL:
DECLARE #Names_tmp NVARCHAR(max);
select #Names_tmp =
COALESCE(#Names_tmp + ' UNION ALL ', '') +
FromTable.Name
from FromTable
FromTable structure:
Key Name Other Columns ...
1 name_1 asd
2 name_2 asd
3 name_3 asd
PRINT CAST(#Names_tmp AS NTEXT)
result:
name_1 UNION ALL name_2 UNION ALL name 3
I see no need to use plpgsql for this matter. PostgreSQL aggregate functions should do it:
CREATE TEMPORARY TABLE t (id INT, name TEXT, asd TEXT);
INSERT INTO t VALUES (1,'name_1','asd'),
(2,'name_2','asd'),
(3,'name_3','asd');
SELECT ARRAY_TO_STRING(ARRAY_AGG(name),' UNION ALL ') FROM t;
SELECT STRING_AGG(name, ' UNION ALL ') FROM t;
Result:
------------------------------------------
name_1 UNION ALL name_2 UNION ALL name_3
(1 Zeile)
Use STRING_AGG
[SQL Fiddle][1]
Query 1:
select string_agg(name,' UNION ALL ') as res from t
Results:
| res |
|------------------------------------------|
| name_1 UNION ALL name_2 UNION ALL name_3 |

PostgreSQL mass insert into a table?

I need to mass insert all the values from col_a into another table. I can do it one at a time like this:
INSERT INTO table_2 (col_a_id)
SELECT 'col_a_id'
FROM table_1
WHERE col_a = 'x';
But is there a way I can just insert all the columns?
EDIT
Lets say I have this table:
Col_a | Col_b |
------------------------
1 | a |
2 | b |
3 | c |
Instead of checking what is in col_a can I just insert each instance of col_a into a table? so I'll have 1, 2 & 3 in table_2?
INSERT INTO table_2 (col1, col2, col3, .... , coln)
SELECT col1, col2, col3, .... , coln
FROM table_1
WHERE col_a = 'x';
Note: String are separated by single quote
SELECT 'this is a string'
Fieldname use double quote:
SELECT "myFieldName", "col1"
EDIT:
If you want check all columns for 'x'
WHERE 'x' IN (col1, col2, col3, .... , coln)

How to compare two identicals tables data of each column in postgres?

I want compare two table's all column values.The two table is identical tables means column number is same and primary key is same. can any one suggest query which compare such two tables in postgres.
The query should give the column name and what is the two different value of two tables.Like this
pkey | column_name | table1_value | table2_value
123 | bonus | 1 | 0
To get all different rows you can use:
select *
from table_1 t1
join table_2 t2 on t1.pkey = t2.pkey
where t1 is distinct from t2;
This will only compare rows that exist in both tables. If you also want to find those that are missing in on of them use a full outer join:
select coalesce(t1.pkey, t2.pkey) as pkey,
case
when t1.pkey is null then 'Missing in table_1'
when t2.pkey is null then 'Missing in table_2'
else 'At least one column is different'
end as status,
*
from table_1 t1
full ojoin table_2 t2 on t1.pkey = t2.pkey
where (t1 is distinct from t2)
or (t1.pkey is null)
or (t2.pkey is null);
If you install the hstore extension, you can view the differences as a key/value map:
select coalesce(t1.pkey, t2.pkey) as pkey,
case
when t1.pkey is null then 'Missing in table_1'
when t2.pkey is null then 'Missing in table_2'
else 'At least one column is different'
end as status,
hstore(t1) - hstore(t2) as values_in_table_1,
hstore(t2) - hstore(t1) as values_in_table_2
from table_1 t1
full ojoin table_2 t2 on t1.pkey = t2.pkey
where (t1 is distinct from t2)
or (t1.pkey is null)
or (t2.pkey is null);
Using this sample data:
create table table_1 (pkey integer primary key, col_1 text, col_2 int);
insert into table_1 (pkey, col_1, col_2)
values (1, 'a', 1), (2, 'b', 2), (3, 'c', 3), (5, 'e', 42);
create table table_2 (pkey integer primary key, col_1 text, col_2 int);
insert into table_2 (pkey, col_1, col_2)
values (1,'a', 1), (2, 'x', 2), (3, 'c', 33), (4, 'd', 52);
A possible result would be:
pkey | status | values_in_table_1 | values_in_table_2
-----+----------------------------------+-------------------+------------------
2 | At least one column is different | "col_1"=>"b" | "col_1"=>"x"
3 | At least one column is different | "col_2"=>"3" | "col_2"=>"33"
4 | Missing in table_1 | |
5 | Missing in table_2 | |
Example data:
create table test1(pkey serial primary key, str text, val int);
insert into test1 (str, val) values ('a', 1), ('b', 2), ('c', 3);
create table test2(pkey serial primary key, str text, val int);
insert into test2 (str, val) values ('a', 1), ('x', 2), ('c', 33);
This simple query gives a complete information on differences of two tables (including rows missing in one of them):
(select 1 t, * from test1
except
select 1 t, * from test2)
union all
(select 2 t, * from test2
except
select 2 t, * from test1)
order by pkey, t;
t | pkey | str | val
---+------+-----+-----
1 | 2 | b | 2
2 | 2 | x | 2
1 | 3 | c | 3
2 | 3 | c | 33
(4 rows)
In Postgres 9.5+ you can transpose the result to the expected format using jsonb functions:
select pkey, key as column, val[1] as value_1, val[2] as value_2
from (
select pkey, key, array_agg(value order by t) val
from (
select t, pkey, key, value
from (
(select 1 t, * from test1
except
select 1 t, * from test2)
union all
(select 2 t, * from test2
except
select 2 t, * from test1)
) s,
lateral jsonb_each_text(to_jsonb(s))
group by 1, 2, 3, 4
) s
group by 1, 2
) s
where key <> 't' and val[1] <> val[2]
order by pkey;
pkey | column | value_1 | value_2
------+--------+---------+---------
2 | str | b | x
3 | val | 3 | 33
(2 rows)
I tried all of the above answer.Thanks guys for your help.Bot after googling I found a simple query.
SELECT <common_column_list> from table1
EXCEPT
SELECT <common_column_list> from table2.
It shows all the row of table1 if any table1 column value is different from table2 column value.
Not very nice but fun and it works :o)
Just replace public.mytable1 and public.mytable2 by correct tables and
update the " where table_schema='public' and table_name='mytable1'"
select * from (
select pkey,column_name,t1.col_value table1_value,t2.col_value table2_value from (
select pkey,generate_subscripts(t,1) ordinal_position,unnest(t) col_value from (
select pkey,
(
replace(regexp_replace( -- null fields
'{'||substring(a::character varying,'^.(.*).$') ||'}' -- {} instead of ()
,'([\{,])([,\}])','\1null\2','g'),',,',',null,')
)::TEXT[] t
from public.mytable1 a
) a) t1
left join (
select pkey,generate_subscripts(t,1) ordinal_position,unnest(t) col_value from (
select pkey,
(
replace(regexp_replace( -- null fields
'{'||substring(a::character varying,'^.(.*).$') ||'}' -- {} instead of ()
,'([\{,])([,\}])','\1null\2','g'),',,',',null,')
)::TEXT[] t
from public.mytable2 a
) a) t2 using (pkey,ordinal_position)
join (select * from information_schema.columns where table_schema='public' and table_name='mytable1') c using (ordinal_position)
) final where COALESCE(table1_value,'')!=COALESCE(table2_value,'')

How to Pivot on caption?

I am trying to pivot rows into columns with Tsql and also eliminate Nulls. How do I do this? My current query:
IF OBJECT_ID(N'tempdb..#test_data') IS NOT NULL drop table #test_data
create table #test_data (
question_caption varchar(max),
[0] varchar(max),
[1] varchar(max),
[2] varchar(max),
[3] varchar(max))
insert #test_data values('q1','abc',Null,Null,Null)
insert #test_data values('q2',Null,'def',Null,Null)
insert #test_data values('q3',Null,Null,'ghi',Null)
insert #test_data values('q4',Null,Null,Null,'jkl')
select * from #test_data
pivot (
Max([0])
For question_caption in ([0],[1],[2],[3])
) as PivotTable
Output:
question_caption 0 1 2 3
q1 abc NULL NULL NULL
q2 NULL def NULL NULL
q3 NULL NULL ghi NULL
q4 NULL NULL NULL jkl
What I want:
q1 q2 q3 q4
abc def ghi jkl
How can I achieve this? The above query has the error:
Msg 265, Level 16, State 1, Line 4
The column name "0" specified in the PIVOT operator conflicts with the existing column name in the PIVOT argument.
I have tried multiple Pivot examples, but all of them have resulted in one error or another.
You can do with a simple max case:
select [q1]=max(case when question_caption = 'q1' then [0] else null end),
[q2]=max(case when question_caption = 'q2' then [1] else null end),
[q3]=max(case when question_caption = 'q3' then [2] else null end),
[q4]=max(case when question_caption = 'q4' then [3] else null end)
from #test_data
or the pivot:
select [q1], [q2], [q3], [q4]
from ( select question_caption,
coalesce([0],[1],[2],[3])
from #test_data
) s (c, v)
pivot (max(v) for c in ([q1], [q2], [q3], [q4])) p

How get file name from full path in select?

I have a table A as:
Col1 Col2
1 D:\Akagane2\Source\SubModule\ExtractText.vb
2 D:\Akagane2\Source\SubModule\ExtractText.vb
I want select output a table has data as
Col1 Col2
1 ExtractText.vb
2 ExtractText.vb
Select in postgresql,
Can you help me ?
Something like
SELECT RIGHT('D:\Akagane2\Source\SubModule\ExtractText.vb', POSITION('\' in REVERSE('D:\Akagane2\Source\SubModule\ExtractText.vb')) -1 );
On PostgreSQL.
mole=> CREATE TABLE A (Col1 INTEGER, Col2 VARCHAR);
CREATE TABLE
mole=> INSERT INTO A VALUES (1, 'D:\Akagane2\Source\SubModule\ExtractText.vb');
INSERT 0 1
mole=> INSERT INTO A VALUES (2, 'D:\Akagane2\Source\SubModule\ExtractText.vb');
INSERT 0 1
mole=> SELECT * FROM A;
col1 | col2
------+---------------------------------------------
1 | D:\Akagane2\Source\SubModule\ExtractText.vb
2 | D:\Akagane2\Source\SubModule\ExtractText.vb
(2 rows)
mole=> SELECT Col1, REGEXP_REPLACE(Col2, '.*\\', '') AS col2 FROM A;
col1 | col2
------+----------------
1 | ExtractText.vb
2 | ExtractText.vb
(2 rows)