tags:

views:

37

answers:

3

My base table is like:

ColumnA|ColumnB
---------------
   A   |  C1
   A   |  C2
   A   |  C3
   B   |  C1
   B   |  C3
   C   |  C4

I want to read records from the base table and write it into the below table:

ColumnA | C1 | C2 | C3 | C4
----------------------------
   A    | Y  |  Y | Y  | N
   B    | Y  |  N | Y  | N
   C    | N  |  N | N  | Y

I don't want to use a cursor, but I don't know if that's possible or not.

Thanks

A: 

assuming you can SELECT the information you like, then you can write the insert as the result of that selection.

Randy
did you read the question at all my friend ?!!
oshin
+2  A: 

Have a look at the PIVOT command. From there you can do a INSERT INTO ... SELECT ...

SELECT ColumnA, [C1], [C2], [C3], [C4]
 FROM (SELECT * FROM table) t 
PIVOT
(
 Count(ColumnB)
 FOR ColumnB IN ([C1], [C2], [C3], [C4])
) As Pvt 
Chris Diver
As I need just Y or N how can I use a case statement here ?I'm trying case count(columnB) = 0 then 'N' ELSE 'Y' END but i'm getting error :Incorrect syntax near the keyword 'case'.
oshin
@oshin: pivot is inflexible in demanding `<aggregation function>(<column being aggregated>)`. Appended a pivot version to my answer that works around that, but please accept Chris Diver's answer if you prefer pivot :)
Andomar
You would have to put a case around each of the `[Cx]` in the select statement.
Chris Diver
+1  A: 

One (usually fast) way would be group by:

insert  NewTable (ColumnA, C1, C2, C3, C4)
select  ColumnA
,       IsNull(max(case when ColumnB = 'C1' then 'Y' end), 'N')
,       IsNull(max(case when ColumnB = 'C2' then 'Y' end), 'N')
,       IsNull(max(case when ColumnB = 'C3' then 'Y' end), 'N')
,       IsNull(max(case when ColumnB = 'C4' then 'Y' end), 'N')
from    OldTable
group by
        ColumnA

Another way is subqueries, like:

insert  NewTable (ColumnA, C1, C2, C3, C4)
select  src.ColumnA
,       case when exists (select * from OldTable ot 
                          where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C1') 
                  then 'Y' else 'N' end
,       case when exists (select * from OldTable ot 
                          where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C2') 
                  then 'Y' else 'N' end
,       case when exists (select * from OldTable ot 
                          where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C3') 
                  then 'Y' else 'N' end
,       case when exists (select * from OldTable ot 
                          where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C4') 
                  then 'Y' else 'N' end
from    (
        select  distinct ColumnA
        from    OldTable
        ) src

Or, adapted from Chris Diver's answer, with pivot:

select  ColumnA
,       case when C1 > 0 then 'Y' else 'N' end C1
,       case when C2 > 0 then 'Y' else 'N' end C2
,       case when C3 > 0 then 'Y' else 'N' end C3
,       case when C4 > 0 then 'Y' else 'N' end C4
from    OldTable src
pivot   (
        count(ColumnB)
        for ColumnB IN ([C1], [C2], [C3], [C4])
        ) pvt
Andomar
+1. This is easier if/when the number of columns to pivot is known at design-time, and is small enough to manage with copy/pasting those subqueries.
p.campbell
in group by why are you using MAX ?
oshin
@oshin: You have to specify a way for the database to aggregate values from multiple rows. The expression inside `max()` returns 'Y' for a match and `null` for no match. The `max()` of that is `Y` if a matching row was found, and `null` otherwise.
Andomar
I'm using the group by solution because I compared pivot run time with group by and group by is better .so I'll accept your answer .thanks
oshin