我对我在SQL Server 2008
数据库中编写的特定查询有疑问。这是一个(更大)更大的查询的一部分,但我会简化其中的内容,以便更容易隔离我正在尝试做的事情。
我有一个表TableX
,两列:
IDX (int) identity
VarX (varchar(20))
我有两个辅助表,TableY
和TableZ
。两者都有两列,
TableY
IDY (int) identity
VarY (varchar(20))
和TableZ
IDZ (int) identity
VarZ (varchar(20))
我正在插入第四个表格,我们称之为TableA
。 TableA
有三列:
IDA (int) identity
IDY (int)
IDZ (int)
此表中的IDY和IDZ字段是表Y和表Z中标识列的外键。
听起来很复杂,但它的连接非常简单。这是它变得有趣的地方。
因此TableX
中的数据可能如下所示:
IDX | VarX
--------------
1 | ABC
2 | ABC-LMN
TableY
中的数据:
IDY | VarY
----------------
1 |ABC
2 | HIJ
TableZ
中的数据:
IDZ | VarZ
----------------
1 | LMN
2 | OPQ
基本上,VarX
(第二列)要么是单个varchar字符串,要么是连字符连接的两个空格。如果是单个字符串,没有连字符,则表Y中始终匹配。匹配将位于VarY
TableY = VarX
中的TableX
上。我会抓取相关的ID(IDY
),然后在TableA
的插页中使用它。
在第1行的示例中,TableA
中的插入内容为(null, 1, null)
现在在第2行的情况下,它有两个用连字符分隔的字符串。因此,TableA
中的插入最终会为(null, 1, 1)
。
所以我的问题是这个......我如何使用相应的连接来表示插入来处理这种类型的逻辑?我确定它必须是一个案例陈述......因为我不是DBA所以有很多麻烦可视化完整的查询......任何帮助都表示赞赏。
答案 0 :(得分:2)
没有必要制作这个动态SQL,除非proc是它的一部分需要它。
INSERT INTO TableA (IDY,IDZ)
SELECT ty.IDY, tz.IDZ
FROM TableX tx
LEFT JOIN TableY ty ON ty.VarY =
(CASE WHEN CHARINDEX('-', tx.VarX) = 0 THEN tx.VarX
ELSE LEFT(tx.VarX, CHARINDEX('-', tx.VarX) - 1) END)
LEFT JOIN TableZ tz ON tz.VarZ =
CASE WHEN CHARINDEX('-', tx.VarX) = 0 THEN NULL
ELSE RIGHT(tx.VarX, LEN(tx.VarX) - CHARINDEX('-', tx.VarX)) END
我故意忽略在TableA.IDA
中插入NULL,因为我不知道你为什么要尝试在身份列中插入NULL,或者甚至可能。我还假设VarX
中的数据不会出现退化情况,例如'-'
,'ZXC-'
,'ASD-BNM '
等。
答案 1 :(得分:1)
我改变了它,似乎可以简化为:
DECLARE @x TABLE (IDX INT, VarX VARCHAR(20))
INSERT @x VALUES (1, 'ABC'), (2, 'ABC-LMN')
DECLARE @y TABLE (IDY INT, VarY VARCHAR(20))
INSERT @y VALUES (1, 'ABC'), (2, 'HIJ')
DECLARE @z TABLE (IDZ INT, VarZ VARCHAR(20))
INSERT @z VALUES (1, 'LMN'), (2, 'OPQ')
DECLARE @a TABLE (IDA INT IDENTITY(1, 1), IDY INT, IDZ INT)
INSERT @a
SELECT y.IDY,
z.IDZ
FROM @x x
LEFT JOIN @y y ON y.VarY = LEFT(x.VarX, LEN(y.VarY))
LEFT JOIN @z z ON z.VarZ = RIGHT(x.VarX, LEN(z.VarZ)) AND CHARINDEX('-', x.VarX) <> 0
SELECT *
FROM @a