Combine two rows in single column with same Id - sql

This is currently how I return values. but I want to combine rows that have the same Id's. I tried using the unpivot but I couldn't get it to work.
here's my query:
SELECT * FROM
(
SELECT
ID,
Setup,
Message
FROM myViewHere
)
AS tempTable
UNPIVOT
(
[Message]
FOR Test
IN (ID, Setup)
) AS PVT
This is the result of myViewHere
|ID | Setup | Message |
|---|--------|----------|
| 1 | Header | myHeader |
|---|--------|----------|
| 1 | Footer | myFooter |
What I want to achieve:
|ID | Header | Footer |
|---|----------|----------|
| 1 | myHeader | myFooter |
|---|----------|----------|

Typical pivot case https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
Assumed table name is "source"
SELECT ID, [Header], [Footer]
FROM source
PIVOT
( max(Message) FOR Setup IN ([Header], [Footer])) p;
See test on sqlfeedle http://sqlfiddle.com/#!6/7635f/7

you can change your view query to be like below
SELECT * FROM
(
SELECT
ID,
Setup,
Message
FROM myViewHere
)
AS tempTable
UNPIVOT
(
[Message]
FOR Test
IN (ID, Setup)
) AS UNPVT
PIVOT
(
MAX([Message])
FOR [Setup]
IN ([Header], [Footer])
)PVT

Related

How can you sort string value or array in SQL

Hello Stackoverflow SQL experts,
What I am looking for:
A way to sort string of text in Snowflake SQL.
Example:
My table looks like something like this:
---------------------
| ID | REFS |
---------------------
| ID1 | 'ANN,BOB' |
| ID2 | 'BOB,ANN' |
---------------------
As you can see my ID1 and ID2 are referred by both Ann and Bob.
But because they were inputted in different orders, they aren't recognized as a group.
Is there a way to sort the String/list values in REF? to clean up REFs?
so when I do counts and group bys. it would be
--------------------------
| REFS | COUNT(ID) |
--------------------------
| 'ANN,BOB' | 2 |
--------------------------
Instead of....
--------------------------
| REFS | COUNT(ID) |
--------------------------
| 'ANN,BOB' | 1 |
| 'BOB,ANN' | 1 |
--------------------------
What I have tried:
TO_ARRAY(REFS) - But this just creates two lists, ['ANN','BOB'] and ['BOB','ANN']
SPLIT(REFS,',') - This also just creates
I have other REF lists containing all sorts of combinations.
'BOB,CHRIS,ANN'
'BOB,CHRIS'
'CHRIS'
'DAVE,ANN'
'ANN,ERIC'
'FRANK,BOB'
...
You should fix the data model! Storing multiple values in a string is a bad idea. That said, you can split, unnest, and reaggregate. I think this works in Snowflake:
select t.*,
(select list_agg(s.value, ',') within group (order by s.value)
from table(split_to_table(t.refs, ',')) s
) normalized_refs
from t;
WITH data(id, refs) as (
SELECT * FROM VALUES
('ID1', 'ANN,BOB'),
('ID2', 'BOB,ANN'),
('ID3', 'CHRIS,BOB,ANN')
)
SELECT order_arry, count(distinct(id)) as count
FROM (
SELECT array_agg(val) WITHIN GROUP (ORDER BY val) over (partition by id) as order_arry, id
FROM (
SELECT d.id, trim(s.value) as val
FROM data d, lateral split_to_table(d.refs, ',') s
)
)
GROUP BY 1 ORDER BY 1;
gives:
ORDER_ARRY COUNT
[ "ANN", "BOB" ] 2
[ "ANN", "BOB", "CHRIS" ] 1
but as Gordon notes, the partiton by is not needed thus the distinct is also not needed;
SELECT ordered_arry, count(id) as count
FROM (
SELECT id, array_agg(val) WITHIN GROUP (ORDER BY val) as ordered_arry
FROM (
SELECT d.id, trim(s.value) as val
FROM data d, lateral split_to_table(d.refs, ',') s
)
GROUP BY 1
)
GROUP BY 1 ORDER BY 1;

Oracle Pivot Based on Multiple Columns

I am fairly new to Pivoting and trying to Pivot based on two columns.
Data I have:
Data I want to Achieve after pivoting:
My Query which is Flawed:
select *
from
(
select ISSUEID,ANSWER, ANSWERCOMMENT,QUESTION ,QUESTIONID
from issue_survey
WHERE ISSUEID = 6877
) d
pivot
(
max(QUESTION)
for QUESTIONID in (1 QUESTION1,2 QUESTION2, 3 QUESTION3)
) piv;
The Results I am getting with this flawed query:
Any suggestions with this are appreciated. Thank you!
Try:
select *
from
(
select ISSUEID,ANSWER, ANSWERCOMMENT,QUESTION ,
rownum rn
from issue_survey
WHERE ISSUEID = 6877
) d
pivot
(
max(QUESTION) as question, max(Answer) as answer,
max( ANSWERCOMMENT ) as ANSWERCOMMENT
for rn in ( 1 ,2 , 3 )
) piv;
Demo: http://www.sqlfiddle.com/#!4/e5aba7/6
| ISSUEID | 1_QUESTION | 1_ANSWER | 1_ANSWERCOMMENT | 2_QUESTION | 2_ANSWER | 2_ANSWERCOMMENT | 3_QUESTION | 3_ANSWER | 3_ANSWERCOMMENT |
|---------|-------------------|----------|-----------------|--------------|----------|-----------------|-----------------|----------|-----------------|
| 6877 | Do you wanna wait | YES | TEST1 | How about it | Its okay | TEST2 | Sample question | (null) | TEST3

Simple SQL Pivot returning null

I am having one of those days.
I am trying to pivot the data below into columns
ID | SplitString
-------------------
| 1 | ABC
| 2 | ABC03082017
| 3 | 03082017
| 4 | 1
| 5 | TestData
So far I have the code below but when I run it, it is returning nulls, the columns have the correct header but the data is all null.
select *
from
(
select ID,splitData from dbo.fn_splitstring(#RawData_Header, '|')
) src
pivot
(
MAX(ID) for splitData in ([Identifier], [ProviderCode], [FileDate],[Code],[FileName])
) piv;
The first part of the pivot script is working correctly and returning the table above.
EDIT**
I am trying to return the data similar to the image below
Thanks for your help
Noelle
If you want to use PIVOT, you have to change your code to:
select [1] AS [Identifier], [2] AS [ProviderCode], [3] AS [FileDate], [4] AS [Code], [5] AS [FileName]
from
(
select ID,splitData from dbo.fn_splitstring(#RawData_Header, '|')
) src
pivot
(
MAX(splitData) for Id in ([1],[2],[3],[4],[5])
) piv;
Read more about PIVOT and UNPIVOT.

SQL: List/aggregate all items for one corresponding transaction id

I have the following table in a vertica db:
+-----+------+
| Tid | Item |
+-----+------+
| 1 | A |
| 1 | B |
| 1 | C |
| 2 | B |
| 2 | D |
+-----+------+
And I want to get this table:
+-----+-------+-------+-------+
| Tid | Item1 | Item2 | Item3 |
+-----+-------+-------+-------+
| 1 | A | B | C |
| 2 | B | D | |
+-----+-------+-------+-------+
Keep in mind that I don't know the maximum item number a transaction_id (Tid) can have, and the amount of items per Tid is not constant. I tried using join and where but could not get it to work properly. Thanks for the help.
There is no PIVOT ability in Vertica. Columns can not be defined on the fly as part of the query. You have to specify.
There are perhaps other options, such as concatenating them in an aggregate using a UDX, such as what you will find in this Stack Overflow answer. But this will put them into a single field.
The only other alternative would be to build the pivot on the client side using something like Python. Else you have to have a way to generate the column lists for your query.
For my example, I am assuming you are dealing with a unique (Tid, Item) set. You may need to modify to suite your needs.
First you would need to determine the max number if items you need to support:
with Tid_count as (
select Tid, count(*) cnt
from mytable
group by 1
)
select max(cnt)
from Tid_count;
And let's say the most Items you had to support was 4, you would then generate a sql to pivot:
with numbered_mytable as (
select Tid,
Item,
row_number() over (partition by Tid order by Item) rn
from mytable
)
select Tid,
MAX(decode(rn,1,Item)) Item1,
MAX(decode(rn,2,Item)) Item2,
MAX(decode(rn,3,Item)) Item3,
MAX(decode(rn,4,Item)) Item4
from numbered_mytable
group by 1
order by 1;
Or if you don't want to generate SQL, but know you'll never have more than X items, you can just create a static form that goes to X.
You can try this:
Create table #table(id int,Value varchar(1))
insert into #table
select 1,'A'
union
select 1,'B'
union
select 1,'C'
union
select 2,'B'
union
select 2,'D'
select id,[1] Item1,[2] Item2,[3] Item3 from
(
select id,Dense_rank()over(partition by id order by value)Rnak,Value from #table
)d
Pivot
(Min(value) for Rnak in ([1],[2],[3]))p
drop table #table

How do I Pivot Vertical Data to Horizontal Data SQL with Variable Row Lengths?

Okay I have the following table.
Name ID Website
Aaron | 2305 | CoolSave1
Aaron | 8464 | DiscoWorld1
Adriana | 2956 | NewCin1
Adriana | 5991 | NewCin2
Adriana | 4563 NewCin3
I would like to transform it into the following way.
Adriana | 2956 | NewCin1 | 5991 | NewCin2 | 4563 | NewCin3
Aaron | 2305 | CoolSave1 | 8464 | DiscoWorld | NULL | NULL
As you can see i am trying to take the first name from the first table and make a single row with all the IDs / Websites associated with that name. The problem is, there is a variable amount of websites that may be associated with each name. To handle this i'd like to just make a table with with the number of fields sequal to the max line item, and then for the subsequent lineitems, plug in a NULL where there are not enough data.
In order to get the result, you will need to apply both the UNPIVOT and the PIVOT functions to the data. The UNPIVOT will take the columns (ID, website) and convert them to rows, once this is done, then you can PIVOT the data back into columns.
The UNPIVOT code will be similar to the following:
select name,
col+'_'+cast(col_num as varchar(10)) col,
value
from
(
select name,
cast(id as varchar(11)) id,
website,
row_number() over(partition by name order by id) col_num
from yt
) src
unpivot
(
value
for col in (id, website)
) unpiv;
See SQL Fiddle with Demo. This gives a result:
| NAME | COL | VALUE |
-------------------------------------
| Aaron | id_1 | 2305 |
| Aaron | website_1 | CoolSave1 |
| Aaron | id_2 | 8464 |
| Aaron | website_2 | DiscoWorld1 |
As you can see I applied a row_number() to the data prior to the unpivot, the row number is used to generate the new column names. The columns in the UNPIVOT must also be of the same datatype, I applied a cast to the id column in the subquery to convert the data to a varchar prior to the pivot.
The col values are then used in the PIVOT. Once the data has been unpivoted, you apply the PIVOT function:
select *
from
(
select name,
col+'_'+cast(col_num as varchar(10)) col,
value
from
(
select name,
cast(id as varchar(11)) id,
website,
row_number() over(partition by name order by id) col_num
from yt
) src
unpivot
(
value
for col in (id, website)
) unpiv
) d
pivot
(
max(value)
for col in (id_1, website_1, id_2, website_2, id_3, website_3)
) piv;
See SQL Fiddle with Demo.
The above version works great if you have a limited or known number of values. But if the number of rows is unknown, then you will need to use dynamic SQL to generate the result:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME( col+'_'+cast(col_num as varchar(10)))
from
(
select row_number() over(partition by name order by id) col_num
from yt
) t
cross apply
(
select 'id' col union all
select 'website'
) c
group by col, col_num
order by col_num, col
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT name,' + #cols + '
from
(
select name,
col+''_''+cast(col_num as varchar(10)) col,
value
from
(
select name,
cast(id as varchar(11)) id,
website,
row_number() over(partition by name order by id) col_num
from yt
) src
unpivot
(
value
for col in (id, website)
) unpiv
) x
pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute(#query);
See SQL Fiddle with Demo. Both versions give the result:
| NAME | ID_1 | WEBSITE_1 | ID_2 | WEBSITE_2 | ID_3 | WEBSITE_3 |
------------------------------------------------------------------------
| Aaron | 2305 | CoolSave1 | 8464 | DiscoWorld1 | (null) | (null) |
| Adriana | 2956 | NewCin1 | 4563 | NewCin3 | 5991 | NewCin2 |