如何将未知数量的行加入另一行?

时间:2010-12-14 16:36:50

标签: sql sql-server-2005

我有这种情况:

表A:

---------------
ID| SOME_VALUE|
---------------
1 | 123223    |
2 | 1232ff    |
---------------

表B:

------------------
ID | KEY | VALUE |
------------------
23 | 1   | 435   |
24 | 1   | 436   |
------------------

KEY是对表A的ID的引用。我可以以某种方式加入这些表,以便得到以下结果:

表C

-------------------------
ID| SOME_VALUE|    |    |
-------------------------
1 | 123223    |435 |436 |
2 | 1232ff    |    |    |
-------------------------

表C应该能够具有任何给定数量的列,具体取决于表B中找到的匹配值的数量。

我希望这足以解释我在这之后的事情。

感谢。

3 个答案:

答案 0 :(得分:3)

您需要使用动态PIVOT子句才能执行此操作。

编辑:

好的,所以我已经完成了一些游戏并基于以下示例数据:

Create Table TableA
(
IDCol int,
SomeValue varchar(50)
)
Create Table TableB
(
IDCol int,
KEYCol int,
Value varchar(50)
)

Insert into TableA
Values (1, '123223')
Insert Into TableA
Values (2,'1232ff')
Insert into TableA
Values (3, '222222')

Insert Into TableB
Values( 23, 1, 435)
Insert Into TableB
Values( 24, 1, 436)

Insert Into TableB
Values( 25, 3, 45)
Insert Into TableB
Values( 26, 3, 46)

Insert Into TableB
Values( 27, 3, 435)
Insert Into TableB
Values( 28, 3, 437)

您可以执行以下动态SQL。

declare @sql varchar(max)
declare @pivot_list varchar(max)
declare @pivot_select varchar(max)

Select 
        @pivot_list = Coalesce(@Pivot_List + ', ','') + '[' + Value +']',
        @Pivot_select = Coalesce(@pivot_Select, ', ','') +'IsNull([' + Value +'],'''') as [' + Value + '],'
From 
(
Select distinct Value From dbo.TableB 
)PivotCodes

Set @Sql = '
;With p as (

Select a.IdCol,
        a.SomeValue,
        b.Value
From dbo.TableA a
Left Join dbo.TableB b on a.IdCol = b.KeyCol
)
Select IdCol, SomeValue ' + Left(@pivot_select, Len(@Pivot_Select)-1) + '
From p
Pivot ( Max(Value) for Value in (' + @pivot_list + '
        )
    )as pvt
'

exec (@sql)

这为您提供以下输出:

alt text

虽然这在目前有效,但维持是一场噩梦。我建议尝试在其他地方实现这些结果。即不在SQL中!

祝你好运!

答案 1 :(得分:2)

正如Barry已经充分说明的那样,可以使用动态数据透视表获得多个列。

我有一个可以为您提供所需内容的解决方案,除了它将所有值放入单个VARCHAR列中。如果您可以拆分这些结果,那么您就可以获得所需的结果。

此方法是SQL Server 2005中的一个技巧,可用于从一列值中形成字符串。

CREATE TABLE #TableA (
   ID INT,
   SomeValue VARCHAR(50)
);
CREATE TABLE #TableB (
   ID INT,
   TableAKEY INT,
   BValue VARCHAR(50)
);

INSERT INTO #TableA VALUES (1, '123223');
INSERT INTO #TableA VALUES (2, '1232ff');
INSERT INTO #TableA VALUES (3, '222222');

INSERT INTO #TableB VALUES (23, 1, 435);
INSERT INTO #TableB VALUES (24, 1, 436);
INSERT INTO #TableB VALUES (25, 3,  45);
INSERT INTO #TableB VALUES (26, 3,  46);
INSERT INTO #TableB VALUES (27, 3, 435);
INSERT INTO #TableB VALUES (28, 3, 437);

SELECT
   a.ID
   ,a.SomeValue
   ,RTRIM(bvals.BValues) AS ValueList
FROM #TableA AS a
OUTER APPLY (
   -- This has the effect of concatenating all of
   -- the BValues for the given value of a.ID.
   SELECT b.BValue + ' ' AS [text()]
   FROM #TableB AS b
   WHERE a.ID = b.TableAKEY
   ORDER BY b.ID
   FOR XML PATH('')
) AS bvals (BValues)
ORDER BY a.ID
;

你会得到这个结果:

ID  SomeValue  ValueList
--- ---------- --------------
1   123223     435 436
2   1232ff     NULL
3   222222     45 46 435 437

答案 2 :(得分:0)

这看起来像数据库不应该做的事情。首先;根据您要存储的内容,表不能具有任意数量的列。因此,无论如何,您必须设置最大数量的值。您可以使用逗号分隔值作为该单元格的值(或类似的类似枢轴的解决方案)来解决此问题。

然而;如果你有表A和B;我建议保留这两张桌子;因为它们看起来很规范。如果输入a.some_value需要b.value列表,则以下sql查询会给出该列表。

从a,b中选择b.value,其中b.key = a.id a.some_value ='INPUT_VALUE';