SQL Server,将两条记录合并到一条记录中

时间:2014-10-21 13:19:53

标签: sql sql-server

我们有这些表

CREATE TABLE tbl01
(
    [id] int NOT NULL PRIMARY KEY,
    [name] nvarchar(50) NOT NULL
)

CREATE TABLE tbl02
(
    [subId] int NOT NULL PRIMARY KEY ,
    [id] int NOT NULL REFERENCES tbl01(id),
    [val] nvarchar(50) NULL,
    [code] int NULL
)

如果我们运行此查询:

SELECT  
   tbl01.id, tbl01.name, tbl02.val, tbl02.code
FROM    
   tbl01 
INNER JOIN 
   tbl02 ON tbl01.id = tbl02.id

我们得到了这些结果:

-------------------------------
id  | name  | val       | code
-------------------------------
1   | one   | FirstVal  | 1
1   | one   | SecondVal | 2
2   | two   | YourVal   | 1
2   | two   | OurVal    | 2
3   | three | NotVal    | 1
3   | three | ThisVal   | 2
-------------------------------

您可以看到每两行都与相同的" id"

相关

问题是:我们需要为每个id检索一条包含所有val的记录,每个val将根据列code <的值返回列中/ p>

if(code = 1) then val as val-1
else if (code = 2) then val as val-2

像这样:

-------------------------------
id  | name  | val-1     | val-2
-------------------------------
1   | one   | FirstVal  | SecondVal
2   | two   | YourVal   | OurVal
3   | three | NotVal    | ThisVal
-------------------------------

有什么建议吗?

5 个答案:

答案 0 :(得分:2)

使用可以使用MAX和Group By来实现此目的

SELECT  id,
        name,
        MAX([val1]) [val-1],
        MAX([val2]) [val-2]
FROM    ( SELECT    tbl01.id, tbl01.name,
                    CASE code
                      WHEN 1 THEN tbl02.val
                      ELSE ''
                    END [val1],
                    CASE code
                      WHEN 2 THEN tbl02.val
                      ELSE ''
                    END [val2]
          FROM      tbl01
                    INNER JOIN tbl02 ON tbl01.id = tbl02.id
        ) Tbl
GROUP BY id, name

答案 1 :(得分:1)

如果总是只有两个值,您可以加入它们甚至更容易,将它们分组:

SELECT  tbl01.id as id, Min(tbl01.name) as name, MIN(tbl02.val) as val-1, MAX(tbl02.val) as val-2
FROM    tbl01 
INNER JOIN tbl02 ON tbl01.id = tbl02.id
GROUP BY tbl02.id

注意:如果不需要,此查询将始终将最低值放在第一列中,最高值放在第二列中:使用连接查询:

加入查询

如果您总是希望第一列中的代码1和第二列中的代码2:

SELECT  tbl01.id as id, tbl01.name as name, tbl02.val as val-1, tbl03.val as val-2
    FROM    tbl01 
    INNER JOIN tbl02 ON tbl01.id = tbl02.id
    ON tbl02.code = 1
    INNER JOIN tbl03 ON tbl01.id = tbl03.id
    ON tbl03.code = 2

可变数量的列

只有在通过在代码或t-sql存储过程中构建查询时才能获得可变数量的列。

我的建议: 如果它总是值:在查询中加入它们,如果没有,让你的服务器端代码转换数据。 (或者甚至更好,找到一种方法,使其无法转换数据)

答案 2 :(得分:1)

答案 3 :(得分:1)

你已经得到了一些答案,但是有人使用PIVOT作为替代。好处是,如果以后需要额外的列,这种方法很容易扩展

-- SETUP TABLES
DECLARE @t1 TABLE (
    [id] int NOT NULL PRIMARY KEY,
    [name] nvarchar(50) NOT NULL
)
DECLARE @t2 TABLE(
    [subId] int NOT NULL PRIMARY KEY ,
    [id] int NOT NULL,
    [val] nvarchar(50) NULL,
    [code] int NULL
)

-- SAMPLE DATA
INSERT @t1  ( id, name )
VALUES  ( 1, 'one'), (2, 'two'), (3, 'three')
INSERT @t2
        ( subId, id, val, code )
VALUES  ( 1,1,'FirstVal', 1), ( 2,1,'SecondVal', 2)
       ,( 3,2,'YourVal', 1), ( 4,2,'OurVal', 2)
       ,( 5,3,'NotVal', 1), ( 6,3,'ThisVal', 2)


-- SELECT (using PIVOT)

SELECT id, name, [1] AS 'val-1', [2] AS 'val-2' 
FROM
( 
SELECT t2.id, t1.name, t2.val, t2.code 
FROM @t1 AS t1 JOIN  @t2 AS t2 ON t2.id = t1.id
) AS src
PIVOT
(
    MIN(val)
    FOR code IN ([1], [2])
) AS pvt

结果:

id  name    val-1       val-2
---------------------------------
1   one     FirstVal    SecondVal
2   two     YourVal     OurVal
3   three   NotVal      ThisVal

答案 4 :(得分:0)

试试这个 - 它使用了一个pivot函数,但它也创建了依赖于代码的动态列

 DECLARE @ColumnString varchar(200)
 DECLARE @sql varchar(1000)


CREATE TABLE #ColumnValue
(
  Value varchar(500)
)

INSERT INTO #ColumnValue (Value)
SELECT DISTINCT '[' + 'value' + Convert(Varchar(20),ROW_NUMBER() Over(Partition by id Order by id )) + ']'
FROM Test

SELECT @ColumnString = COALESCE(@ColumnString + ',', '') + Value
FROM #ColumnValue
Drop table #ColumnValue



SET @sql =
'
SELECT *
FROM
(
SELECT
        id,name,val,''value'' + Convert(Varchar(20),ROW_NUMBER() Over(Partition by id Order by id ))as [values]
FROM Test
) AS P
    PIVOT
(
    MAX(val) FOR [values] IN ('+@ColumnString+')
) AS pv
'

--print @sql 
EXEC (@sql)