根据多个条件和列将列数据拆分为单独的列

时间:2016-01-13 12:22:37

标签: sql sql-server

我需要拆分下面给出的列数据,包括查询和值

create table dep (
    a1 varchar(17),
    a2 char(2),
    a3 varchar(50),
    a4 int,
    a5 int,
    a6 int, 
    a7 char(1)
)

insert into dep (a1,a2,a3,a4,a5,a6,a7) values(507,01,'abc1',30,1,2,1)
insert into dep (a1,a2,a3,a4,a5,a6,a7) values(507,02,'abc2',31,2,1,0)
insert into dep (a1,a2,a3,a4,a5,a6,a7) values(507,03,'abc3',32,1,6,1)
insert into dep (a1,a2,a3,a4,a5,a6,a7) values(507,04,'abc4',33,1,3,0)
insert into dep (a1,a2,a3,a4,a5,a6,a7) values(507,05,'abc5',34,2,4,1)

需要拆分列a2及其对应列a3,a4,a5。 输出如下:

a1  b1  b2  b3  b4  b5  c1    c2 c3  c4 c5  d1   d2 d3  d4  d5
507 abc 01  30  1   2   abc3  03 32  1  6   abc5 05 34  2   4

如果a7为0则应跳过该记录。

1 个答案:

答案 0 :(得分:0)

IMHO;如果我正确理解你的要求;我认为 - 作为静态查询 - 你可以使用这样的查询:

SELECT a1
    , MAX(CASE WHEN rn = 1 THEN a2 END) b1
    , MAX(CASE WHEN rn = 1 THEN a3 END) b2
    , MAX(CASE WHEN rn = 1 THEN a4 END) b3
    , MAX(CASE WHEN rn = 1 THEN a5 END) b4
    , MAX(CASE WHEN rn = 1 THEN a6 END) b5
    , MAX(CASE WHEN rn = 2 THEN a2 END) c1
    , MAX(CASE WHEN rn = 2 THEN a3 END) c2
    , MAX(CASE WHEN rn = 2 THEN a4 END) c3
    , MAX(CASE WHEN rn = 2 THEN a5 END) c4
    , MAX(CASE WHEN rn = 2 THEN a6 END) c5
    , MAX(CASE WHEN rn = 3 THEN a2 END) d1
    , MAX(CASE WHEN rn = 3 THEN a3 END) d2
    , MAX(CASE WHEN rn = 3 THEN a4 END) d3
    , MAX(CASE WHEN rn = 3 THEN a5 END) d4
    , MAX(CASE WHEN rn = 3 THEN a6 END) d5
FROM (
    SELECT *, ROW_NUMBER() OVER (ORDER BY a2) as rn
    FROM dep
    WHERE a7 = 1) t
GROUP BY a1;

动态SQL的解决方案可以是这样的:

DECLARE @sql varchar(max) = 'SELECT a1';
SELECT
    @sql = @sql + ',MAX(CASE WHEN rn = ' + CAST(rn as varchar(5)) + ' THEN a2 END) ' + CHAR(64 + rn) + '1' 
                + ',MAX(CASE WHEN rn = ' + CAST(rn as varchar(5)) + ' THEN a3 END) ' + CHAR(64 + rn) + '1'
                + ',MAX(CASE WHEN rn = ' + CAST(rn as varchar(5)) + ' THEN a4 END) ' + CHAR(64 + rn) + '1'
                + ',MAX(CASE WHEN rn = ' + CAST(rn as varchar(5)) + ' THEN a5 END) ' + CHAR(64 + rn) + '1'
FROM (
    SELECT *
        , ROW_NUMBER() OVER (ORDER BY a2) as rn
    FROM #dep
    WHERE a7 = 1) t;

SET @sql = @sql + 'FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY a2) as rn FROM dep WHERE a7 = 1) t GROUP BY a1';
EXEC(@sql);

编辑:在您的情况下,我认为您可以使用以下查询:

DECLARE @sql nvarchar(max) = 'SELECT FamilyId', @maxDepe int;

SELECT @maxDepe = max(seq) 
FROM (
    SELECT *
        , ROW_NUMBER() OVER (PARTITION BY FamilyId ORDER BY MemberID) As seq
    FROM depe) dt;

WITH CTE(i) AS (
    SELECT 1
    UNION ALL
    SELECT i + 1
    FROM CTE 
    WHERE i < @maxDepe)
SELECT @sql = @sql +
    ',MAX(CASE WHEN seq = ' + CAST(i as varchar(3)) + ' THEN MemberName END) Dependent_' + CAST(i as varchar(3)) +
    ',MAX(CASE WHEN seq = ' + CAST(i as varchar(3)) + ' THEN Age END) Age_' + CAST(i as varchar(3)) + 
    ',MAX(CASE WHEN seq = ' + CAST(i as varchar(3)) + ' THEN Gender END) Gender_' + CAST(i as varchar(3)) +
    ',MAX(CASE WHEN seq = ' + CAST(i as varchar(3)) + ' THEN RelationCode END) RelationCode_' + CAST(i as varchar(3))
FROM CTE;

SELECT @sql = @sql + ' FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY FamilyId ORDER BY MemberID) seq FROM depe) dt GROUP BY FamilyId';

EXEC(@sql);