2

我正在尝试完成以下任务:

SELECT col1, col2 FROM table1
UNION
SELECT col2, col3 FROM table2

结果:

col1, col2, col3
1   , 1   , NULL
NULL, 1   , 1

返回列行的并集。您可以将其视为 FULL OUTER JOIN 的 UNION 等价物。

这个问题的简单答案是:

SELECT col1, col2, NULL AS col3 FROM table1
UNION
SELECT NULL AS col1, col2, col3 FROM table2

然而,动态 T-SQL 和 dbo.sp_executesql 很难做到这一点,如果涉及大量 UNION,则生成的查询可能会太长。

我能想到的最佳解决方案是创建一个包含所有可能列的临时表,然后将每个选择依次插入到临时表中,如下所示:

CREATE TABLE #temp ( col1 int, col2 int, col3 int )
INSERT INTO #temp ( col1, col2 ) SELECT col1, col2 FROM table1
INSERT INTO #temp ( col2, col3 ) SELECT col2, col3 FROM table2

但这需要提前知道列名是什么。我的特定场景和这个问题假设如果列名匹配类型也匹配。事实上,我试图操作的列都是相同的类型。

有没有更简单的方法来做到这一点?

谢谢!

4

4 回答 4

1

我对您的问题的解释是,鉴于有关动态 SQL 和列名和数据类型的讨论,您希望能够支持临时查询......

此查询将为您提供特定表的列列表及其数据类型:

SELECT @columnName = c.name AS columnName,
       @columnDataType = ty.name AS columnDataType
  FROM SYS.TABLES ta
  JOIN SYS.COLUMNS c ON c.object_id = ta.object_id
  JOIN SYS.TYPES ty ON ty.user_type_id = c.user_type_id
 WHERE ta.name = '[your_table_name]'

这会填充@columnName&@columnDataType变量,因此您可以在其他地方使用它们。

您至少需要提供列名和该列所在的表名,以便为单个列获取有意义的数据。之后,就是构建你想要做什么的逻辑,以便创建你想要的查询。

一种更简单的方法是确定大多数情况所需的查询是什么。
可悲的是,当你问的时候,答案通常是“一切”。对于那个回应,我会列出一些事情,以支持你需要一定数量的货币和时间的一切。强调将需求分解为可管理的部分更便宜、更快捷——这也将使您能够获得反馈。可能没有人会使用该功能的一小部分,或者它根本不是用户需要的。学习管理客户期望。

于 2009-12-06T21:05:45.720 回答
0

快速尝试后,我可以在不跳过大量燃烧的 hackiness 的情况下进入 T-SQL 的最接近方法是使用带有错误条件的 FULL OUTER JOIN ......例如

DECLARE @TableA TABLE (Col1 INTEGER IDENTITY(1,1), Col2 INTEGER)
DECLARE @TableB TABLE (Col2 INTEGER IDENTITY(1,1), Col3 INTEGER)

INSERT @TableA VALUES (1)
INSERT @TableA VALUES (11)
INSERT @TableB VALUES (2)
INSERT @TableB VALUES (222)

SELECT *
FROM @TableA a
    FULL OUTER JOIN @TableB b ON 0 = 1

不过,您会从结果中看到,Col2 在结果集中包含了两次……它没有合并为一个。

我的建议是在您的代码中处理这个问题,而不是在 T-SQL 中尝试它 - 将多个结果集返回到您的调用代码并处理不同的模式。如果您真的需要它作为一个结果集,那么该调用代码是否可以不将结果合并为一个?

于 2009-12-06T20:48:43.960 回答
0

这会有助于(加入一些虚拟专栏)提供一些见解吗?

declare @t1 table(col1 varchar(10),col2 varchar(10))
declare @t2 table(col2 varchar(10),col3 varchar(10))
insert into @t1 select '1','1' union all select '10','1'
insert into @t2 select '1',null union all select '10','1'

;with cte1 as(select ROW_NUMBER() over(order by getdate()) rn1, t1.* from @t1 t1)
,cte2 as(select ROW_NUMBER() over(order by getdate()) rn2, t2.* from @t2 t2)
select c1.col1,c1.col2,c2.col3
from cte1 c1 
full outer join cte2 c2
on c1.rn1 = c2.rn2

输出:

col1    col2    col3
1   1   NULL
10  1   1
于 2009-12-07T05:05:59.410 回答
0

我在这个问题上认输了,写了一堆讨厌的动态 T-SQL 并用 sp_executesql 执行它。谢谢您的帮助!

于 2009-12-13T05:12:20.773 回答