2010-12-14 29 views
3

我有这样的情形:如何将未知行数加入另一行?

表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.

我希望这足以解释我在这里之后。

感谢。

+0

我个人会改变你的设计。关键值表是一种非常困难的设计,可以有效且正确地工作。如果您确实需要键值对,那么关系数据库可能不是存储它们的最佳位置。一个noSQL数据库可能是一个更好的选择。 – HLGEM 2010-12-14 18:19:32

+0

是的,我知道这不是一个很好的方法来解决这个问题,但我只需要这个一次性的东西,它不会在任何应用程序中实现。 – picknick 2010-12-14 19:27:00

回答

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中!

祝你好运!

+0

谢谢!我同意“不在SQL”的观点,但这只是一次性的事情。 – picknick 2010-12-14 19:29:21

0

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

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

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

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 
+0

我实际上已经结束了你的解决方案,但接受的答案接近我原来的问题。谢谢! – picknick 2010-12-14 19:27:51

+0

没关系。我已经在接受的答案中建立了这种解决方案,就像作者所说,它是有效的,但这是一个维护噩梦。 – eksortso 2010-12-14 22:38:33