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;
Related
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) )
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;
I need to populate a table columns in SQL Server 2008R2 on win 7.
The table 1
Id1 Id2 value1
---------------------
1 a 58218
1 b 2888
1 c 916
I need to create a table 2 such that
Id1 value1 value1_b_over_a value1_c_over_a
------------------------------------------------------
1 58218 2888/58218 916/58218
I would like to get the table with only one SQL query.
Any help would be appreciated.
You can do this with conditional aggregation:
select t1.id1,
sum(case when id2 = 'a' then value1 end) as value1,
sum(case when id2 = 'b' then value1 end) / sum(case when id2 = 'a' then value1 end) as value1_b_over_a,
sum(case when id2 = 'c' then value1 end) / sum(case when id2 = 'a' then value1 end) as value1_c_over_a,
from table1 t1
group by t1.id1;
Note: SQL Server does integer arithmetic. If you want a number, then cast value1 to an appropriate numeric type.
select t1.id1,
sum(case when id2 = 'a' then value1 end) as value1,
sum(case when id2 = 'b' then cast(value1 as float) end) / sum(case when id2 = 'a' then value1 end) as value1_b_over_a,
sum(case when id2 = 'c' then cast(value1 as float) end) / sum(case when id2 = 'a' then value1 end) as value1_c_over_a,
from table1 t1
group by t1.id1;
You could do a simple pivot and then do your operations.
select result.id1,
result.a value1,
cast(result.b as decimal) / result.a value1_b_over_a,
cast(result.c as decimal) / result.a value1_c_over_a
from (
select *
from table1 t
pivot(sum(value1) for id2 in (
[a],
[b],
[c]
)) as pivotrow
) result;
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.
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;