用多行替换一行以形成另一张表

时间:2019-04-29 10:31:11

标签: sql sql-server

我有两个表:
表1:

Number| Code | Value
-------+------+-----
Garden |A0,C2 | 100
Garden |rest  | 500
House  |A0,C2 | 100
House  |rest  | 500

表2:

|Code|
+-----+
|A0  |
|B1  |
|C2  |
|D3  |
|E4  |

我想要一个看起来像这样的表:

Number| Code | Value
-------+------+-----
Garden |A0    | 100
Garden |B1    | 500
Garden |C2    | 100
Garden |D3    | 500
Garden |E4    | 500
House  |A0    | 100
House  |B1    | 500
House  |C2    | 100
House  |D3    | 500
House  |E4    | 500

有人知道我如何获得此表的SQL语句吗?

无法更改表1或表2

2 个答案:

答案 0 :(得分:1)

您应该修复table1,以便它不使用以逗号分隔的字符串表示的列表。为此,您应该有一个单独的表。这样做的原因很多。

假设您被某人困住了,否则它的数据模型确实非常糟糕,则可以使用join。有几种方法。 SQL Server 2017+具有内置的string_split()函数。

然后,您要使用cross join生成行,并使用left join s引入所需的值:

select n.number, t2.code, coalesce(t1.value, t1rest.value) as value
from (select distinct number from table1) n cross join
     table2 t2 left join
     table1 t1 
     on t1.number = n.number and ',' + t1.codes + ',' like '%,' + t2.code + ',%' left join
     table1 t1rest
     on t1rest.number = n.number and t1rest.codes = 'rest';

Here是db <>小提琴

答案 1 :(得分:1)

我不喜欢这种解决方案,因为带有JOIN的{​​{1}}很丑。我强烈建议在此修复您的数据模型。您不应在表中使用定界数据,也不应使用EXISTS之类的值来表示您想要除先前定义的值以外的所有其他值。您在此处获得的结果集是一个规范化的数据集,而这正是存储数据的方式:

'rest'

db<>fiddle

如果您不使用SQL Server 2016+,则将无法使用CREATE TABLE Table1 (Number varchar(6), --A number is a varchar? Code varchar(50), [Value] int); INSERT INTO dbo.Table1 (Number, Code, [Value]) VALUES ('Garden','A0,C2',100), ('Garden','rest',500), ('House','A0,C2',100), ('House','rest',500); CREATE TABLE Table2 (Code char(2)); INSERT INTO dbo.Table2 (Code) VALUES ('A0'), ('B1'), ('C2'), ('D3'), ('E4'); GO WITH CTE AS( SELECT T1.Number, SS.[value] AS Code, T1.[Value] FROM dbo.Table1 T1 CROSS APPLY STRING_SPLIT(T1.Code, ',') SS) SELECT C.Number, T2.Code, C.[Value] FROM CTE C JOIN dbo.Table2 T2 ON C.Code = T2.Code OR (C.Code = 'rest' AND NOT EXISTS (SELECT 1 FROM CTE e WHERE e.Number = C.Number AND e.Code = T2.Code)) GO DROP TABLE dbo.Table1; DROP TABLE dbo.Table2; 。因此,我建议查找“ XML拆分器”或STRING_SPLIT