Data is present in the screenshot as table format. I want to convert into desired format as mentioned below.
Table describe :
Table A
(branch_code, branch_name, branch_state, hol1, hol2, hol3....hol100)
Expected Output
TAMF046 14/01/2021
TAMF046 15/01/2021
TAMF046 26/01/2021
KERF047 26/01/2021
KERF047 11/03/2021
KERF047 02/04/2021
This is exactly what UNPIVOT is for
with t(id, c1, c2, c3) as (
select 1, 'a', 'b', 'c' from dual union all
select 2, 'aa', 'bb', 'cc' from dual
)
select *
from t
unpivot (
val
for col in (
c1 as 'A1',
c2 as 'A2',
c3 as 'A3'
)
)
val is the new column that will contain values from columns c1 c2 c3.
col is the new column that will contain the name of the column from where the val comes from.
A1 A2 A3 are the values you want to fill in the col for each unpivoted column (these aliases can be omitted if you are ok with the original column names).
Use union
Eg:
select Branch_Code, Hol1 from MyTable
union
select Branch_Code, Hol2 from MyTable
etc
WITH HOLIDAY
AS (
SELECT BRANCH_CODE,HOL1,HOL2,HOL3,HOL4,HOL5,HOL6,HOL7,HOL8,HOL9,HOL10,HOL11,HOL12,HOL13,HOL14,HOL15,HOL16,HOL17,HOL18,HOL19,HOL20,HOL21,HOL22,HOL23,HOL24,HOL25,HOL26,HOL27,HOL28,HOL29,HOL30,HOL31,HOL32,HOL33,HOL34,HOL35,HOL36,HOL37,HOL38,HOL39,HOL40,HOL41,HOL42,HOL43,HOL44,HOL45,HOL46,HOL47,HOL48,HOL49,HOL50,HOL51,HOL52,HOL53,HOL54,HOL55,HOL56,HOL57,HOL58,HOL59,HOL60,HOL61,HOL62,HOL63,HOL64,HOL65,HOL66,HOL67,HOL68,HOL69,HOL70,HOL71,HOL72,HOL73,HOL74,HOL75,HOL76,HOL77,HOL78,HOL79,HOL80,HOL81,HOL82,HOL83,HOL84,HOL85,HOL86,HOL87,HOL88,HOL89,HOL90,HOL91,HOL92,HOL93,HOL94,HOL95,HOL96,HOL97,HOL98,HOL99,HOL100
FROM CUST_HOLIDAY_MASTER
WHERE BRANCH_CODE = I.BRANCH_CODE
)
SELECT BRANCH_CODE , COLVALUE FROM abc
unpivot
( colvalue for col in (HOL1,HOL2,HOL3,HOL4,HOL5,HOL6,HOL7,HOL8,HOL9,HOL10,HOL11,HOL12,HOL13,HOL14,HOL15,HOL16,HOL17,HOL18,HOL19,HOL20,HOL21,HOL22,HOL23,HOL24,HOL25,HOL26,HOL27,HOL28,HOL29,HOL30,HOL31,HOL32,HOL33,HOL34,HOL35,HOL36,HOL37,HOL38,HOL39,HOL40,HOL41,HOL42,HOL43,HOL44,HOL45,HOL46,HOL47,HOL48,HOL49,HOL50,HOL51,HOL52,HOL53,HOL54,HOL55,HOL56,HOL57,HOL58,HOL59,HOL60,HOL61,HOL62,HOL63,HOL64,HOL65,HOL66,HOL67,HOL68,HOL69,HOL70,HOL71,HOL72,HOL73,HOL74,HOL75,HOL76,HOL77,HOL78,HOL79,HOL80,HOL81,HOL82,HOL83,HOL84,HOL85,HOL86,HOL87,HOL88,HOL89,HOL90,HOL91,HOL92,HOL93,HOL94,HOL95,HOL96,HOL97,HOL98,HOL99,HOL100)
)
WHERE COLVALUE IS NOT NULL;
This is the way which i try to this but if anyone has any other way using dynamic query. Please share your views,
Table T1
C1 | C2
-----+------
A,B | C,D
Code:
DECLARE
l_varchar VARCHAR2(100);
BEGIN
SELECT C1||','||C2 INTO l_varchar FROM T1;
END;
Now I need to split values in l_varchar based on COMMA delimiter.
If I try to split as given in http://sqlfiddle.com/#!4/b42db/7
I get:
A
B
C
D
But I need:
A,B
C,D
Can you please help me to get this desired output.
Can I do something while concatenating the strings, so that later I will be able to split it?
Below query is used to concatenate, can this be tweaked?
SELECT C1||','||C2 INTO l_varchar FROM T1;
Query used to split comma delimited string:
select
regexp_substr(C1||','||c2 ,'[^,]+', 1, level) As str
from
(select 'A,B' c1, 'C,D' c2 from dual)
CONNECT BY LEVEL <= regexp_count(C1||','||c2, ',') + 1
Unless I am misunderstanding, what you are trying to do is not possible unless you use a different delimiter. Example :
SELECT C1||';'||C2 INTO l_varchar FROM T1;
here is a very nice and correct way to do it:
SELECT *
FROM t1
UNPIVOT (unpivoted_column FOR original_column
IN (c1 AS 'C1', c2 AS 'C2'));
For any further clarifications don't hesitate to ask me.
Ted.
Best possible way is to use the REGEXP combinations. Hope the below snippet helps you to get the desired result.
SELECT regexp_substr(a.c, '[^*]+', 1, level) TXT
FROM
(SELECT COL1
||'*'
||COL2
||'*'
||COL3 C
FROM
(SELECT 'A,B' COL1,'C,D' COL2,'E,F' COL3 FROM DUAL
)
)A
CONNECT BY LEVEL <= LENGTH(A.C)-LENGTH(REPLACE(A.C,'*',''))+1;
Basically, when given a list of strings,
I want to create a table with select statement.
For example,
"A", "B", "C",
I want to create a table as a sub-select like:
sub-select
+---------+
| "A" |
+---------+
| "B" |
+---------+
| "C" |
+---------+
How do I do this in redshift and postgres?
Thanks!
Update:
select 'a' as A;
is sort of what I want that returns:
a
+---------+
| "a" |
+---------+
How do I have multiple rows for this column a from the query select 'a' as A;
One of the way to convert a column value to multiple rows is using split_part function and UNION.
Here is an example.
Source Table:
=> CREATE TABLE t_csv (value varchar(64));
=> INSERT INTO t_csv VALUES ('"A","B","C"');
=> INSERT INTO t_csv VALUES ('"D","E"');
=> INSERT INTO t_csv VALUES ('"F","G","H","I"');
=> SELECT * FROM t_csv;
value
-----------------
"D","E"
"A","B","C"
"F","G","H","I"
(3 rows)
Here is the query to get multiple rows.
=> WITH a AS (SELECT value FROM t_csv)
SELECT * FROM
(
SELECT split_part(a.value,',',1) AS value FROM a
UNION
SELECT split_part(a.value,',',2) AS value FROM a
UNION
SELECT split_part(a.value,',',3) AS value FROM a
UNION
SELECT split_part(a.value,',',4) AS value FROM a
)
WHERE value != '';
value
-------
"A"
"B"
"C"
"D"
"E"
"F"
"G"
"H"
"I"
(9 rows)
Have no chance to test it in db, but something like that
select * INTO table from (
SELECT CAST('A' AS VARCHAR(100)) AS col
UNION ALL
SELECT 'B' AS col
UNION ALL
SELECT 'C' AS col
) a
You can use string_to_array and unnest
select *
from unnest(string_to_array('"A","B","C"', ','))
(But I don't know if that is available in Redshift)
Is there any way to write a select record starting with a particular record? Suppose I have an table with following data:
SNO ID ISSUE
----------------------
1 A1 unknown
2 A2 some_issue
3 A1 unknown2
4 B1 some_issue2
5 B3 ISSUE4
6 B1 ISSUE4
Can I write a select to start showing records starting with B1 and then the remaining records? The output should be something like this:
4 B1 some_issue2
6 B1 ISSUE4
1 A1 unknown
2 A2 some_issue
3 A1 unknown2
5 B3 ISSUE4
It doesn't matter if B3 is last, just that B1 should be displayed first.
Couple of different options depending on what you 'know' ahead of time (i.e. the id of the record you want to be first, the sno, etc.):
Union approach:
select 1 as sortOrder, SNO, ID, ISSUE
from tableName
where ID = 'B1'
union all
select 2 as sortOrder, SNO, ID, ISSUE
from tableName
where ID <> 'B1'
order by sortOrder;
Case statement in order by:
select SNO, ID, ISSUE
from tableName
order by case when ID = 'B1' then 1 else 2 end;
You could also consider using temp tables, cte's, etc., but those approaches would likely be less performant...try a couple different approaches in your environment to see which works best.
Assuming you are using MySQL, you could either use IF() in an ORDER BY clause...
SELECT SNO, ID, ISSUE FROM table ORDER BY IF( ID = 'B1', 0, 1 );
... or you could define a function that imposes your sort order...
DELIMITER $$
CREATE FUNCTION my_sort_order( ID VARCHAR(2), EXPECTED VARCHAR(2) )
RETURNS INT
BEGIN
RETURN IF( ID = EXPECTED, 0, 1 );
END$$
DELIMITER ;
SELECT SNO, ID, ISSUE FROM table ORDER BY my_sort_sort( ID, 'B1' );
select * from table1
where id = 'B1'
union all
select * from table1
where id <> 'B1'