row convert to column in sql 2008 - sql

I want to convert a series of rows into a series of columns
create table #cusphone(cusid int,cusph1 int)
insert into #cusphone values(1,48509)
insert into #cusphone values(1,48508)
insert into #cusphone values(1,48507)
insert into #cusphone values(2,48100)
so that the output is like this
1 48509 48508 48507
2 48100 null null

You can use the same approach of rank() and then use the new PIVOT function as follows:
with cusCte as(
select cusid,cusph1,RANK() over (partition by cusid order by cusph1) r
from #cusphone)
SELECT cusid, [1] AS C1, [2] AS C2, [3] AS C3
FROM
(SELECT cusid,cusph1,r
FROM cusCte) p
PIVOT
(
MIN (cusph1)
FOR r IN
( [1], [2], [3] )
) AS pvt;

You did not specify the rules by which something should appear in the first column vs the second column so I guessed that this is based on the occurrence (and thus sorting) of the cusph1 value.
With RankedItems As
(
Select cusid, cusph1
, ROW_NUMBER() OVER( PARTITION BY cusid ORDER BY cusph1 DESC) As Num
From #cusphone
)
Select cusid
, Min(Case When Num = 1 Then cusph1 End) As Col1
, Min(Case When Num = 2 Then cusph1 End) As Col2
, Min(Case When Num = 3 Then cusph1 End) As Col3
From RankedItems
Group By cusid

Related

Dynamically converting multiple row values to columns with composite key

I have a following data with 2 Unique Identifiers (ID1, ID2), and multiple values that spread across various times. I am trying to pivot it dynamically, because one combination of ID1 & ID2 do not have a fixed number of Values and Times. Any help is appreciated! Thanks!
DECLARE #DataSource TABLE
(
ID1 INT
,ID2 INT
,Val INT
,[Time] Datetime
)
INSERT INTO #DataSource (ID1, ID2, Val, [Time])
VALUES (1,1,10,'01/01/2021 12:00')
,(1,1,20,'01/01/2021 15:00')
,(1,2,30,'01/02/2021 17:00')
,(1,2,35,'01/02/2021 18:00')
,(2,1,40,'02/02/2021 08:00')
,(2,2,50,'02/02/2021 10:00')
,(2,2,60,'05/01/2021 11:00')
SELECT *
FROM #DataSource
I am trying to pivot it so it looks something like this and Value and Time are next to each other in sequence.
You can group by ROW_NUMBER divided by 2, this gets you every two rows in a group
SELECT
ID1,
ID2,
Val1 = MIN(CASE WHEN rn % 2 = 1 THEN Val END),
Time1 = MIN(CASE WHEN rn % 2 = 1 THEN [Time] END),
Val2 = MIN(CASE WHEN rn % 2 = 0 THEN Val END),
Time2 = MIN(CASE WHEN rn % 2 = 0 THEN [Time] END)
FROM (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY ID1, ID2 ORDER BY [Time])
FROM YourTable t
) t
GROUP BY
t.ID1,
t.ID2,
(t.rn - 1) / 2

SQL Server Trying to convert the data from rows to columns

I have table with data like as below
Crosswalk_id Code
ORG_201 1234
ORG_201 3456
ORG_201 3459
ORG_201 0983
ORG_201 2562
ORG_201 1239
need to convert this into
Crosswalk_id C1 C2 C3 C4 C5 C6
ORG_201 1234 3456 3459 0983 2562 1239
Please help me to achieve this using pivot
Use conditional aggregation with row_number():
select crosswalk_id,
max(case when seqnum = 1 then code end) as c1,
max(case when seqnum = 2 then code end) as c2,
max(case when seqnum = 3 then code end) as c3,
max(case when seqnum = 4 then code end) as c4,
max(case when seqnum = 5 then code end) as c5,
max(case when seqnum = 6 then code end) as c6
from (select t.*,
row_number() over (partition by crosswalk_id order by (select null)) as seqnum
from t
) t
group by crosswalk_id;
You can use the SQL Server PIVOT function, it's made exactly for this purpose, i.e. transform rows to columns.
An example of the PIVOT Function is available here on this blog.
You must include an aggregation clause, the MAX() works pretty well for string values if you do not have duplicates lines.
For the full documentation, please check the official Microsoft doc covering PIVOT and UNPIVOT functions.
NOTE: in your example, you only have one value "ORG_201", you might have more to use the function. And you need to name the columns, based on the values you expect in the [Code] column.
Don't your IDs need to be different???
-- DROP TABLE mytable
CREATE table mytable (
id NVARCHAR(20),
code NVARCHAR(5)
)
GO
INSERT INTO mytable ( id, code ) VALUES ( 'ORG_201', '1234')
INSERT INTO mytable ( id, code ) VALUES ( 'ORG_202', '3456')
INSERT INTO mytable ( id, code ) VALUES ( 'ORG_203', '3459')
INSERT INTO mytable ( id, code ) VALUES ( 'ORG_204', '0983')
INSERT INTO mytable ( id, code ) VALUES ( 'ORG_205', '2562')
INSERT INTO mytable ( id, code ) VALUES ( 'ORG_206', '1239')
SELECT *
FROM mytable
select * from
(
SELECT id, code
FROM mytable
) t
PIVOT (
max(code)
FOR id IN ([ORG_201],[ORG_202],[ORG_203],[ORG_204],[ORG_205],[ORG_206])
) AS PivotTable;

I want distinct numbers with choice as columns using datetime ascending order

there is a table with
1001 vsp,science,BBA 25-05-2020
1001 vsp,Maths,Btech 26-05-2020
1001 vsp,Maths,Btech 27-05-2020
1002 hyd,science,BBA 24-05-2020
1002 blr,Maths,Btech 25-05-2020
I want
1001 vsp,science,bba vsp,Maths,Btech vsp,Maths,Btech
You need one of my favorite combo to achieve your goal:
CTE (to create proper sub request): https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql
ROW_NUMBER (to rank your rows): https://learn.microsoft.com/en-us/sql/t-sql/functions/row-number-transact-sql
PIVOT (to pivot your results): https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot
And now the solution:
WITH orderedCourse AS
(
SELECT GroupId,
CourseLabel,
ROW_NUMBER() OVER (PARTITION BY GroupId ORDER BY CourseDate) AS CourseNumber
FROM #myCourses
)
SELECT TOP (1) GroupId, [1], [2], [3], [4]
FROM
(
SELECT GroupId,
CourseLabel,
CourseNumber
FROM orderedCourse
) AS src
PIVOT
(
MIN(CourseLabel) -- default agregate
FOR CourseNumber IN ([1], [2], [3], [4] /*... if you have more courses by group*/)
) AS pvt
ORDER BY GroupId
Which give the result:
1001 vsp,science,BBA vsp,Maths,Btech vsp,Maths,Btech NULL
I used this code to declare the table:
INSERT INTO #myCourses
SELECT 1001, 'vsp,science,BBA', CAST('25-05-2020' AS date) UNION ALL
SELECT 1001, 'vsp,Maths,Btech', CAST('26-05-2020' AS date) UNION ALL
SELECT 1001, 'vsp,Maths,Btech', CAST('27-05-2020' AS date) UNION ALL
SELECT 1002, 'yd,science,BBA', CAST('24-05-2020' AS date) UNION ALL
SELECT 1002, 'blr,Maths,Btech', CAST('25-05-2020' AS date);
SELECT GroupId,
CourseLabel,
CourseDate,
ROW_NUMBER() OVER (PARTITION BY GroupId ORDER BY CourseDate) AS CourseNumber
FROM #myCourses;
Just use conditional aggregation with row_number():
select col1,
max(case when seqnum = 1 then col2 end),
max(case when seqnum = 2 then col2 end),
max(case when seqnum = 3 then col2 end)
from (select t.*,
row_number() over (partition by col1 order by col3) as seqnum
from t
) t
group by col1;
This has nothing to do with string aggregation. It also doesn't require a plethora of subqueries and CTEs.

convert row into column with asc order in oracle

SELECT * FROM
(
SELECT TEST_NAME, SBNO, VAL
FROM TABLE1
)
PIVOT (
MAX(VAL)
FOR SBNO in (1 value1, 2 value2, 3 value3 ));
Output:
I want to show data in ascending order, like this:
2.3 , 2.4 , 2.5
but result is
2.3 , 2.5 , 2.4
This would do the trick. I have created a new SBNO column, ordering by test_name and value and then PIVOT operator will do the rest.
;with cte as (
select
test_name
,val
,'Value' + cast(ROW_NUMBER() over (partition by test_name order by test_name, val) as varchar(5)) as new_SBNO
from TABLE1
)
select *
from cte
pivot (
max(val)
for new_SBNO in (value1, value2, value3)
) pvt
I would do this using conditional aggregation:
select test_name,
max(case when seqnum = 1 then val end) as value_1,
max(case when seqnum = 2 then val end) as value_2,
max(case when seqnum = 3 then val end) as value_3
from (select t1.*,
row_number() over (partition by test_name order by val asc) as seqnum
from table1 t1
) t1
group by test_name;
You could express this with pivot. And in Oracle, pivot can even be a bit faster. I just find conditional aggregation to be more flexible and simpler to implement.

SQL Row_Number() increase only when the value = 1 for a specific column

I am having some trouble generating row_number() in my SQL query as my expectation. I have this following output of my query-
Now, I want to add row number for all rows where row number will only increase when the value in C1 is = 1. Required output as below-
Any help will be appreciated. TIA
Table Variable:
DECLARE #Table AS TABLE (C1 INT)
INSERT INTO #Table VALUES (1),(4),(1),(1),(4),(1),(3),(4)
SQL 2008 Version
;WITH cteSimulateAnOriginalIdentityKey AS (
SELECT
C1
,OriginalOrder = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
#Table
)
, cteC1RowNumber AS (
SELECT
*
,C1RowNumber = ROW_NUMBER() OVER (PARTITION BY C1 ORDER BY OriginalOrder)
FROM
cteSimulateAnOriginalIdentityKey
)
SELECT
C1
,RN = ISNULL((SELECT MAX(C1RowNumber) FROM cteC1RowNumber r2 WHERE r2.C1 = 1 AND r2.OriginalOrder <= r1.OriginalOrder),1)
FROM
cteC1RowNumber r1
ORDER BY
OriginalOrder
SQL 2012+ version
;WITH cteSimulateAnOriginalIdentityKey AS (
SELECT
C1
,OriginalOrder = ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
#Table
)
, cteC1RowNumber AS (
SELECT
*
,C1RowNumber = ROW_NUMBER() OVER (PARTITION BY C1 ORDER BY OriginalOrder)
FROM
cteSimulateAnOriginalIdentityKey
)
SELECT
C1
,RN = ISNULL(MAX(CASE WHEN C1 = 1 THEN C1RowNumber END) OVER (ORDER BY OriginalOrder),1)
FROM
cteC1RowNumber
ORDER BY
OriginalOrder
RESULT:
C1 RN
1 1
4 1
1 2
1 3
4 3
1 4
3 4
4 4
If you in fact have another column by which to maintain the desired original order you don't need the first cte which is simply simulating that column
Try this:
SELECT C1,
ROW_NUMBER() OVER (PARTITION BY C1 ORDER BY (SELECT 100)) RN
FROM TableNAme
I presume you have another column(s) in your query by which you determine the order of rows; without such a criteria, your whole question is pointless.
The query below will work on SQL Server 2012 or later versions:
declare #Table table (
Id int identity(1,1) not null,
C1 int
);
insert into #Table(C1) values (1),(4),(1),(1),(4),(1),(3),(4);
select t.C1,
sum(case t.C1 when 1 then 1 else 0 end) over(order by t.Id) as [RN]
from #Table t;