Select 列名称基于两个单独的 table 和数据库中的条件
Select column names based on condition in two separate table and database
我在两个单独的数据库中有相同的 table(架构可能不同,所以我使用 'intersect'):
- 来自数据库 1 的 MyTable
- 来自数据库 2 的 MyTable
当当前列的行在 Database1 中具有 NULL 值而在 Database2 中具有 NOT NULL 时,我想获取列名,如果可能的话还包括数据。
查询可以如下所示:
SELECT (
SELECT COLUMN_NAME FROM Database1.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA='dbo'
INTERSECT
SELECT COLUMN_NAME FROM Database2.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA='dbo'
) /* +data ? */
FROM Database1.dbo.MyTable AS MyTable1 INNER JOIN
Database2.dbo.MyTable AS MyTable2 ON MyTable1.id = MyTable2.id
WHERE MyTable1.COLUMN_NAME IS NULL AND MyTable2.COLUMN_NAME IS NOT NULL
OR MyTable2.COLUMN_NAME IS NULL AND MyTable1.COLUMN_NAME IS NOT NULL
但这显然是错误的。
为此你需要动态 SQL,它不会很漂亮。
DECLARE @sql nvarchar(max) = N'SELECT t1.id',
@sel nvarchar(max) = N'',
@clauses nvarchar(max) = N'';
;WITH src(col, name) AS
(
SELECT QUOTENAME(c.name), c.name
FROM Database1.sys.columns AS c
INNER JOIN Database1.sys.tables AS t
ON c.[object_id] = t.[object_id]
WHERE t.name = N'MyTable' AND t.schema_id = 1
INTERSECT
SELECT QUOTENAME(c.name), c.name
FROM Database2.sys.columns AS c
INNER JOIN Database2.sys.tables AS t
ON c.[object_id] = t.[object_id]
WHERE t.name = N'MyTable' AND t.schema_id = 1
),
clauses(clause, sel) AS
(
SELECT clause = char(13) + char(10)
+ N' OR ( (t1.' + col + N' IS NULL AND t2.' + col + N' IS NOT NULL)'
+ char(13) + char(10)
+ ' OR (t1.' + col + N' IS NOT NULL AND t2.' + col + N' IS NULL))',
sel = N',' + char(13) + char(10)
+ N' t1_' + name + N' = t1.' + col
+ N', t2_' + name + N' = t2.' + col
FROM src
WHERE name <> N'id'
)
SELECT @sel += sel, @clauses += clause FROM clauses;
SELECT @sql += @sel
+ char(13) + char(10) + N' FROM Database1.dbo.MyTable AS t1'
+ char(13) + char(10) + N' INNER JOIN Database2.dbo.MyTable AS t2'
+ char(13) + char(10) + N' ON t1.id = t2.id AND (1 = 2' + @clauses + N');';
SELECT @sql;
--EXEC sys.sp_executesql @sql;
输出(假设 MyTable
具有公共列 id
、x
和 y
):
SELECT t1.id,
t1_x = t1.[x], t2_x = t2.[x],
t1_y = t1.[y], t2_y = t2.[y]
FROM Database1.dbo.MyTable AS t1
INNER JOIN Database2.dbo.MyTable AS t2
ON t1.id = t2.id AND (1 = 2
OR ( (t1.[x] IS NULL AND t2.[x] IS NOT NULL)
OR (t1.[x] IS NOT NULL AND t2.[x] IS NULL))
OR ( (t1.[y] IS NULL AND t2.[y] IS NOT NULL)
OR (t1.[y] IS NOT NULL AND t2.[y] IS NULL)));
我在两个单独的数据库中有相同的 table(架构可能不同,所以我使用 'intersect'):
- 来自数据库 1 的 MyTable
- 来自数据库 2 的 MyTable
当当前列的行在 Database1 中具有 NULL 值而在 Database2 中具有 NOT NULL 时,我想获取列名,如果可能的话还包括数据。
查询可以如下所示:
SELECT (
SELECT COLUMN_NAME FROM Database1.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA='dbo'
INTERSECT
SELECT COLUMN_NAME FROM Database2.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA='dbo'
) /* +data ? */
FROM Database1.dbo.MyTable AS MyTable1 INNER JOIN
Database2.dbo.MyTable AS MyTable2 ON MyTable1.id = MyTable2.id
WHERE MyTable1.COLUMN_NAME IS NULL AND MyTable2.COLUMN_NAME IS NOT NULL
OR MyTable2.COLUMN_NAME IS NULL AND MyTable1.COLUMN_NAME IS NOT NULL
但这显然是错误的。
为此你需要动态 SQL,它不会很漂亮。
DECLARE @sql nvarchar(max) = N'SELECT t1.id',
@sel nvarchar(max) = N'',
@clauses nvarchar(max) = N'';
;WITH src(col, name) AS
(
SELECT QUOTENAME(c.name), c.name
FROM Database1.sys.columns AS c
INNER JOIN Database1.sys.tables AS t
ON c.[object_id] = t.[object_id]
WHERE t.name = N'MyTable' AND t.schema_id = 1
INTERSECT
SELECT QUOTENAME(c.name), c.name
FROM Database2.sys.columns AS c
INNER JOIN Database2.sys.tables AS t
ON c.[object_id] = t.[object_id]
WHERE t.name = N'MyTable' AND t.schema_id = 1
),
clauses(clause, sel) AS
(
SELECT clause = char(13) + char(10)
+ N' OR ( (t1.' + col + N' IS NULL AND t2.' + col + N' IS NOT NULL)'
+ char(13) + char(10)
+ ' OR (t1.' + col + N' IS NOT NULL AND t2.' + col + N' IS NULL))',
sel = N',' + char(13) + char(10)
+ N' t1_' + name + N' = t1.' + col
+ N', t2_' + name + N' = t2.' + col
FROM src
WHERE name <> N'id'
)
SELECT @sel += sel, @clauses += clause FROM clauses;
SELECT @sql += @sel
+ char(13) + char(10) + N' FROM Database1.dbo.MyTable AS t1'
+ char(13) + char(10) + N' INNER JOIN Database2.dbo.MyTable AS t2'
+ char(13) + char(10) + N' ON t1.id = t2.id AND (1 = 2' + @clauses + N');';
SELECT @sql;
--EXEC sys.sp_executesql @sql;
输出(假设 MyTable
具有公共列 id
、x
和 y
):
SELECT t1.id,
t1_x = t1.[x], t2_x = t2.[x],
t1_y = t1.[y], t2_y = t2.[y]
FROM Database1.dbo.MyTable AS t1
INNER JOIN Database2.dbo.MyTable AS t2
ON t1.id = t2.id AND (1 = 2
OR ( (t1.[x] IS NULL AND t2.[x] IS NOT NULL)
OR (t1.[x] IS NOT NULL AND t2.[x] IS NULL))
OR ( (t1.[y] IS NULL AND t2.[y] IS NOT NULL)
OR (t1.[y] IS NOT NULL AND t2.[y] IS NULL)));