Teradata SQL pivot multiple results and eliminate duplicate values - sql

I have something like this:
ID Result
1 value1
2 value1
2 value2
3 value1
3 value1
4 value1
4 value2
4 value3
Notice that ID 3 has the same result appearing in two rows.
Thanks to bluefeet (teradata sql pivot multiple occurrences into additional columns), I was able to produce something like this:
ID Result1 Result2 Result3
1 value1
2 value1 value2
3 value1
4 value1 value2 value3
I'm getting what I want, but because ID 3 has multiple results, they are counted as 2 and then included in the second column, which is for those results that return 2 occurrences for one ID.
What I would like it do is simply return the first occurrence of the duplicate ID 3 result in the Result1 column, like this:
ID Result1 Result2 Result3
1 value1
2 value1 value2
3 value1
4 value1 value2 value3
How can I eliminate that duplicate result and prevent it from counting?

TD14.10 finally added DENSE_RANK (which could be used instead of ROW_NUMBER in bluefeet's query), but before you have to add some kind of DISTINCT processing, e.g.:
SELECT id,
MAX(CASE WHEN seq =1 THEN res END) result1,
MAX(CASE WHEN seq =2 THEN res END) result2,
MAX(CASE WHEN seq =3 THEN res END) result3
FROM
(
SELECT id, res, ROW_NUMBER() OVER(PARTITION BY id ORDER BY res) seq
FROM
(
SELECT DISTINCT id, res
FROM yourtable
) d
) d
GROUP BY id
ORDER BY id;

Related

Sql Group by Value1 having count(*) > 1 but with different value 2

Given an SQL table like this
id value1 value2
---------------
1 1 1
2 1 1
3 1 1
4 2 1
5 2 2
6 3 1
I want to find all the value1's that have duplicate value1 (i.e using group by having count(*)>1) but only if they have different values for value2
So in this example I just want to return 2
Im using Postgres
If I understand correctly, this is group by with a having clause:
select value1
from t
group by value1
having min(value2) <> max(value2)
use
select * from ( select * , ROW_NUMBER() OVER(PARTITION BY Value1 ORDER BY Value1 , Value2 ASC) AS RowValue1, ROW_NUMBER() OVER(PARTITION BY Value1 , Value2 ORDER BY Value1 , Value2 ASC) AS RowValue2 from Table_1 ) As TableTmp where TableTmp.RowValue1 <> TableTmp.RowValue2
Or
select * from Table_1 where value1 in (select value1 from Table_1 group by value1 having min(value2) <> max(value2) )

Pivot table in teradata sql

I have data like this:
ID Result
1 value1
2 value1
2 value2
3 value1
4 value1
4 value2
4 value3
How can I accomplish in teradata SQL the pivot table like in Excel.
ID Value1 Value2 ...
1 count of Value1 for ID 1 count of Value2 for ID 1 ...
2 count of Value1 for ID 2 count of Value2 for ID 1 ...
3 ... ... ...
assuming that there is a large number of ID and varying number of Values.
SELECT sum(case when Result='Value1' then ID end) "Value1"
, sum(case when Result='Value2' then ID end) "Value2"
FROM your_table
GROUP BY null;
Not much context can be added here I'm afraid, except this is the way pivots can be implemented in TD up to v15.x
So i found the answer and i would like to share it with you
First of all you need to recalculate the data to know the counts for id||Value
CREATE TABLE myTable_count as (
SELECT ID, Result, count(1) as countOfResult
FROM myTable
group by ID, Result
) WITH DATA
Then you can do a pivot, but you have to know the names of result's
SELECT ID,
sum(CASE WHEN Result='Value1' then countOfResult else NULL END) Value1,
sum(CASE WHEN Result='Value2' then countOfResult else NULL END) Value2
FROM myTable_count
GROUP BY ID;
If it help you give it a vote up.
SELECT
id,
count(
CASE WHEN result1 = 'value1' THEN id END
) AS value1,
COUNT(
CASE WHEN result1 = 'value2' THEN id END
) AS value2,
COUNT(
CASE WHEN result1 = 'value3' THEN id END
) as value3
FROM
pivot_tb1
group by
1;

Select new column based on existing value

I have sample data like below
create Table #Temp(id int, Data1 varchar(10), Data2 bigint)
Insert Into #Temp
Values(1,'Value1',109040774),
(2,'Value2',10000006099758),
(3,'Value3',10000006099758),
(4,'Value1',14538),
(5,'Value2',10000006097458),
(6,'Value3',10000006097458),
(7,'Value1',4454834),
And trying to select new column based on Data1, so the output will be
id Data1 NewColumn
1 Value1 109040774
2 Value2 109040774
3 Value3 109040774
4 Value1 14538 --reset here because same value of Data1 (Value 1 started repeating)
5 Value2 14538
6 Value3 14538
7 Value1 4454834 --reset here because same value of Data1 (Value 1 started repeating)
I was trying to use something like below, but not what I after
SELECT id, Data1,
FIRST_VALUE(Data2) OVER (Partition by Data1 ORDER BY Id ASC) AS NewCol
FROM #Temp
Order By Id
Any help is appreciate
Here is my idea assuming a special value1 defines a new group:
Use a cumulative sum to calculate the number of value1s on or before each row.
This defines a grouping.
Within each group, use first_value().
Hence:
select t.id, t.data1,
first_value(data2) over (partition by grp order by id) as newcolumn
from (select t.*,
sum(case when data1 = 'value1' then 1 else 0 end) over (order by id) as grp
from t
) t;

SQL Server convert a table column values to names and assign 0 to the new columns if no value for a column

I would like to transform a table from rows to columns in SQL Server.
Given table1:
id value1 value2
1 name1 9
1 name1 26
1 name1 15
2 name2 20
2 name2 18
2 name2 61
I need a table like:
id name1 name2
1 9 0
1 26 0
1 15 0
2 0 20
2 0 18
2 0 61
Can pivot help here? An efficient way is preferred to do the convert because the table is large.
I have tried:
select
id, name1, name2
from
(select
id, value1, value2
from table1) d
pivot
(
max(value2)
for value1 in (name1, name2)
) piv;
But, it cannot provide all rows for same ID to combine with 0s.
Thanks
The 'secret' is to add a column to give uniqueness to each row within your 'nameX' groups. I've used ROW_NUMBER. Although PIVOT requires an aggregate, with our 'faked uniqueness' MAX, MIN etc will suffice. The final piece is to replace any NULLs with 0 in the outer select.
(BTW, we're on 2014 so I can't test this on 2008 - apologies)
SELECT * INTO #Demo FROM (VALUES
(1,'name1',9),
(1,'name1',26),
(1,'name1',15),
(2,'name2',20),
(2,'name2',18),
(2,'name2',61)) A (Id,Value1,Value2)
SELECT
Id
,ISNULL(Name1, 0) Name1
,ISNULL(Name2, 0) Name2
FROM
( SELECT
ROW_NUMBER() OVER ( PARTITION BY Id ORDER BY Id ) rn
,Id
,Value1
,Value2
FROM
#Demo ) A
PIVOT ( MAX(Value2) FOR Value1 IN ( [Name1], [Name2] ) ) AS P;
Id Name1 Name2
----------- ----------- -----------
1 9 0
1 26 0
1 15 0
2 0 20
2 0 18
2 0 61
you can do case based aggregation with group by
SQL Fiddle
select id,
max(case when value1 ='name1' then value2 else 0 end) as name1,
max(case when value1 ='name2' then value2 else 0 end) as name2
from Table1
group by id, value1, value2

teradata sql pivot multiple occurrences into additional columns

I have something like this:
ID Result
1 value1
2 value1
2 value2
3 value1
4 value1
4 value2
4 value3
And I'd like to return something like this:
ID Result1 Result2 Result3
1 value1
2 value1 value2
3 value1
4 value1 value2 value3
I've searched on pivots and concats and breaks and I just can't find a simple, sensible solution.
TIA
Unfortunately Teradata doesn't have a PIVOT function but you can use an aggregate function with a CASE expression to get the result.
select id,
max(case when seq =1 then result end) result1,
max(case when seq =2 then result end) result2,
max(case when seq =3 then result end) result3
from
(
select id, res, row_number() over(partition by id order by result) seq
from yourtable
) d
group by id
order by id;
If you have more values for each ID, then you can add more CASE expressions.