sql transformation - rows to column - sql

i have been trying to solve this one image
my initial idea is like this
select name,
CASE
when count(name) = 1 then get first distinct value
when count(name) = 2 then get first distinct value
else get first distinct value
END as val1,
CASE
when count(name) = 1 then null
when count(name) = 2 then get second distinct value
else get second distinct value
END as val2,
CASE
when count(name) = 1 then null
when count(name) = 2 then null
else get third distinct value
END as val3
into desired_table
from source_table
group by name
is my attempt feasible? if so, how do i access the first, second and third distinct values?

use pivot . Your output table was incorrect. The correct form is available in db<>fiddle.
select name,x as value1,y as value2,z as value3
from
(
select *
from t1
) as SourceTable
pivot
(
max(value) for value in(x,y,z)
) as PivotTable
demo in db<>fiddle

You can use conditional aggregation along with row_number():
select name,
max(case when seqnum = 1 then value end) as value_1,
max(case when seqnum = 2 then value end) as value_2,
max(case when seqnum = 3 then value end) as value_3
into desired_table
from (select s.*,
row_number() over (partition by name order by value) as seqnum
from source_table s
) s
group by name;

Related

Selecting 3 rows into 3 columns in sql server

I am trying to select the 3 rows into 3 columns, but i get NULL values.
Here is my code so far:
SELECT * FROM
(
SELECT t_k
FROM m_t_k
WHERE p_id = 5 and t_k_id in (1,2,7)
) src
PIVOT(
MAX()
for t_k in ([1],[2],[3])
) piv
this is the result of the query without the PIVOT
and i want those rows to be on 3 columns
You could use ROW_NUMBER and a Cross Tab to achieve this. This is a bit of a guess, based on the query and image we have though, so it is untested:
SELECT MAX(CASE WHEN RN = 1 THEN sq.term_key END) AS term_key1,
MAX(CASE WHEN RN = 2 THEN sq.term_key END) AS term_key2,
MAX(CASE WHEN RN = 3 THEN sq.term_key END) AS term_key3
FROM (SELECT term_key,
ROW_NUMBER() OVER (ORDER BY term_key) AS RN
FROM mpos_term_key
WHERE profile_id = 5
AND term_keys_type_id IN (1, 2, 7)) sq;

Case statement gives error cound not convert 'ABC' to a float8

I am trying to run below sql statement but getting could not convert to a float. By default return type of case is taking as float. Tried casting it to varchar in Row_num , Name but didn't help. Any help be helpful.
Database = Vertica
SELECT
Name,
ID,
row_num,
(Case when Row_num = 1 Then Name END) +
(Case When Row_num = 2 Then Name END)
FROM table ;
I would try this:
SELECT
Name,
ID,
row_num,
(SELECT Name FROM table WHERE Row_num = 1) +
(SELECT Name FROM table WHERE Row_num = 2) AS ConcatNames
FROM table ;
To concatenate strings in Vertica, use ||:
SELECT Name, ID, row_num,
((Case when Row_num = 1 Then Name END) ||
(Case When Row_num = 2 Then Name END)
)
FROM table ;
I'm not quite sure what this is supposed to do, because one or both case expressions will return NULL.

How to Get row values as columns in SQL?

I have a table Test with two columns.
Id Value
1 A
1 B
1 C
I want to get the result like below,
Id Value1 Value2 value3
1 A B C
How can I done this in SQL Server.
This is a pivot, but you don't have a column for the pivoting. row_number() can provide that. I usually use conditional aggregations for this.
select id,
max(case when seqnum = 1 then value end) as value1,
max(case when seqnum = 2 then value end) as value2,
max(case when seqnum = 3 then value end) as value3
from (select t.*,
row_number() over (partition by id order by (select null)) as seqnum
from t
) t
group by id;
Note that SQL tables represent unordered sets. So, there is no information about ordering and the values could be in any order. If a column does specify the ordering, then include that in the order by rather than select null.

Remove duplicate rows as an additional column

I have a sql table for student records and I have some duplicate rows for the student dimension cause of the major, so now I have something like this:
ID Major
----------
1 CS
1 Mgt
What I want is to combine this two rows in this form:
ID Major Major2
----------
1 CS Mgt
You need a number for pivoting. Then you can pivot using either pivot or conditional aggregation:
select id,
max(case when seqnum = 1 then major end) as major_1,
max(case when seqnum = 2 then major end) as major_2
from (select t.*,
row_number() over (partition by id order by (select null)) as seqnum
from t
) t
group by id;
Note: you should validate that "2" is large enough to count the majors. You can get the maximum using:
select top 1 id, count(*)
from t
group by id
order by count(*) desc;
If you have at most two different values of major:
select a.id as id,
a.major as major,
b.major as major2
from YOUR_TABLE a
left join YOUR_TABLE b on
a.id = b.id
and (b.major is null or a.major > b.major)
This will help you
Select
ID,
(select top 1 Major from <Your_Table> where id=T.Id order by Major) Major,
(case when count(Id)>1 then (select top 1 Major from #temp where id=T.Id order by Major desc) else null end) Major2
from <Your_Table> T
Group By
ID
You can use pivot function directly
SELECT [ID],[CS] AS Major , [Mgt] AS Major2 from Your_Table_Name
PIVOT
(max(Major)for [Major] IN ([CS] , [Mgt]))as p

Transforming rows having dynamic dates into columns

Need to convert this:
DATE VALUE
18-DEC-15 2877544
17-DEC-15 2974276
16-DEC-15 4862020
into
18-DEC-15 17-DEC-15 16-DEC-15
2877544 2974276 4862020
The dates are updated everyday and I need to pick only the latest 3 dates and convert them into columns with the corresponding values below.
I tried using Pivots but I'm able to create the column headers dynamically.
Try this
WITH pivot_data AS (
select date, value from table)
SELECT *
FROM pivot_data
PIVOT (
max(value) --<-- pivot_clause
FOR table --<-- pivot_for_clause
);
A SQL query has well-defined column names, so for variable column names you need dynamic SQL. But, you can do what you want with fixed names:
select max(case when seqnum = 1 then value end) as MostRecentDay,
max(case when seqnum = 2 then value end) as SecondMostRecentDay,
max(case when seqnum = 3 then value end) as ThirdMostRecentDay
from (select t.*, dense_rank() over (order by date desc) as seqnum
from t
) t;
You could even add three columns specifying the date values:
select max(case when seqnum = 1 then value end) as MostRecentDay,
max(case when seqnum = 2 then value end) as SecondMostRecentDay,
max(case when seqnum = 3 then value end) as ThirdMostRecentDay,
max(case when seqnum = 1 then date end) as MostRecentDate,
max(case when seqnum = 2 then date end) as SecondMostRecentDate,
max(case when seqnum = 3 then date end) as ThirdMostRecentDate
from (select t.*, dense_rank() over (order by date desc) as seqnum
from t
) t;
Use Conditional Aggregate to pivot the data
select MAX(case when "DATE" = '18-DEC-15' then VALUE END) as '18-DEC-15',
MAX(case when "DATE" = '17-DEC-15' then VALUE END) as '17-DEC-15',
MAX(case when "DATE" = '16-DEC-15' then VALUE END) as '16-DEC-15'
from yourtable
Note : since dates are unknown, you need to use EXECUTE IMMEDIATE