3

I've a table Columns

enter image description here

and a second table Response in which all data is saved.

enter image description here

Now I want to create a SQL View in which the result should be like this

enter image description here

I tried using pivot

select UserId ,FromDate, ToDate, Project, Comment
from
(
  select R.UserId ,R.Text , C.ColumnName
  from [Columns] C
  INNER JOIN Response R ON C.Id=R.ColumnId
) d
pivot
(
  max(Text)
  for ColumnName in (FromDate, ToDate, Project, Comment)
) piv;

but that didn't worked for me, I also referred this Efficiently convert rows to columns in sql server but was not able to implement it. Any ideas how to achieve the same in SQL View?

Scripts for Tables:

CREATE TABLE [dbo].[Columns](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](1000) NULL,
    [IsActive] [bit] NULL,
 CONSTRAINT [PK_Columns] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

insert into [Columns] values('FromDate',1)
insert into [Columns] values('ToDate',1)
insert into [Columns] values('Project',1)
insert into [Columns] values('Comment',1)

CREATE TABLE [dbo].[Response](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [UserId] [bigint]  NOT NULL,
    [ColumnId] [bigint]  NOT NULL,
    [Text] [nvarchar](max) NULL,
    [IsActive] [bit] NULL,
    CONSTRAINT [PK_Response] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
insert into [Response] values(1,1,'1/1/2012',1)
insert into [Response] values(1,2,'1/2/2012',1)
insert into [Response] values(1,3,'p1',1)
insert into [Response] values(1,4,'c1',1)
insert into [Response] values(2,1,'1/1/2013',1)
insert into [Response] values(2,2,'1/2/2013',1)
insert into [Response] values(2,3,'p2',1)
insert into [Response] values(2,4,'c2',1)
insert into [Response] values(2,1,'1/1/2014',1)
insert into [Response] values(2,2,'1/2/2014',1)
insert into [Response] values(2,3,'p3',1)
insert into [Response] values(2,4,'c3',1)
insert into [Response] values(3,1,'1/1/2015',1)
insert into [Response] values(3,2,'1/2/2015',1)
insert into [Response] values(3,3,'p4',1)
insert into [Response] values(3,4,'c4',1)
5
  • Show what didn't work for you. Commented Nov 18, 2016 at 16:26
  • 1
    Can you show the pivot query you tried to use? Commented Nov 18, 2016 at 16:33
  • @WEI_DBA : shared Commented Nov 18, 2016 at 16:39
  • what happens when a userid is on multiple projects? Commented Nov 18, 2016 at 22:06
  • @DForck42 : Like I mentioned the desired output in my question, each record for the corresponding UserId should come without duplicate records. Commented Nov 21, 2016 at 7:56

3 Answers 3

2

Honestly, if the column types aren't going to change, or you only need a subset of them, you could just filter them out and then join on them rather than write a pivot. I wrote it using a cte, but they could just as easily be sub-queries:

;with fd as
(
    select
        UserID,
        [Text] as FromDate,
        row_number() over (partition by userID order by ID) as DEDUP
    from response
    where ColumnID = 1
),
td as
(
    select
        UserID,
        [Text] as ToDate,
        row_number() over (partition by userID order by ID) as DEDUP
    from response
    where ColumnID = 2
),
p as
(
    select
        UserID,
        [Text] as Project,
        row_number() over (partition by userID order by ID) as DEDUP
    from response
    where ColumnID = 3
),
c as
(
    select
        UserID,
        [Text] as Comment,
        row_number() over (partition by userID order by ID) as DEDUP
    from response
    where ColumnID = 4
)
select
    fd.*,
    td.ToDate,
    p.Project,
    c.Comment
from fd
    inner join td
        on fd.UserId = td.UserId
            and fd.DEDUP = td.DEDUP
    inner join p
        on fd.UserId = p.UserId
            and fd.DEDUP = p.DEDUP
    inner join c
        on fd.UserId = c.UserId
            and fd.DEDUP = c.DEDUP
Sign up to request clarification or add additional context in comments.

5 Comments

your query returns duplicate records, is there any way to get unique records.
@SidM I fixed my typo. let me know if this works correctly now
No, its still giving the duplicate results
@SidM ok, I think I've fixed it
Thanks for the answer :)
0

Try this. I worked on your answer.

select UserId ,FromDate, ToDate, Project, Comment
from
(
  select R.UserId ,R.RText , C.ColumnName
  from [Columns] C
  INNER JOIN Response R ON C.Id=R.ColumnId
) d
pivot
(
  Min(Rtext)
  for ColumnName in (FromDate, ToDate, Project, Comment)
) piv

UNION
select UserId ,FromDate, ToDate, Project, Comment
from
(
  select R.UserId ,R.RText , C.ColumnName
  from [Columns] C
  INNER JOIN Response R ON C.Id=R.ColumnId
) d
pivot
(
  Max(Rtext)
  for ColumnName in (FromDate, ToDate, Project, Comment)
) piv;

2 Comments

max and min functions returns null for date type values, here for columns FromDate and Todate. Also you are considering only two rows for the UserId=2, there can be more rows for any UserId
True. I was going based on your data.
-1

You can query like this

;with cte as 
(
    select r.*, 
    c.name 
    from Response r 
        inner join Columns c
            on r.columnid = c.id
) 
select 
    Userid, 
    max([FromDate]) as [FromDate],
    max([ToDate]) as [ToDate],
    max([Project]) as [Project],
    max([Comment]) as [Comment] 
from cte
pivot
(
    max(Text) for name in ([FromDate], [ToDate], [Project], [Comment])
) p
group by userid

5 Comments

2 problems in the answer, 1 : max function returns null for date type values, here for columns FromDate and Todate. 2 : only 1 row returned for UserId=2
Provide your input sample data as scripts
shared the scripts
Updated answer based on your input scripts. It is working fine for me..
I don't get the result for project p2, did you really run the query you mentioned in your answer or just edited and posted it here. P.S. I didn't downvote your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.