有没有一种方法可以使用 intersect 而无需仅选择不同的值?类似于INTERSECT ALL
。
例如,考虑表 A 和 B
A --> 1, 1, 1, 2, 3, 4
B --> 1, 1, 2
会导致
Result --> 1, 1, 2
编辑
我认为这个link很好地解释了我想要什么。这个other link理解这个问题也很有趣。或this other link更好地解释事件。
编辑2
假设表格:
表A
╔════════╦════╦═══╦════╦════╗
║ A ║ B ║ C ║ D ║ E ║
╠════════╬════╬═══╬════╬════╣
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ House ║ 10 ║ 1 ║ NO ║ -5 ║
║ Monkey ║ 15 ║ 1 ║ OK ║ -1 ║
║ Dog ║ 3 ║ 1 ║ OK ║ -1 ║
╚════════╩════╩═══╩════╩════╝
表B
╔═════╦════╦═══╦════╦════╗
║ A ║ B ║ C ║ D ║ E ║
╠═════╬════╬═══╬════╬════╣
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ Car ║ 15 ║ 1 ║ OK ║ -1 ║
║ Dog ║ 3 ║ 1 ║ OK ║ -1 ║
╚═════╩════╩═══╩════╩════╝
相交(select * from A INTERSECT select * from B
)的答案是:
╔═════╦════╦═══╦════╦════╗
║ A ║ B ║ C ║ D ║ E ║
╠═════╬════╬═══╬════╬════╣
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ Dog ║ 3 ║ 1 ║ OK ║ -1 ║
╚═════╩════╩═══╩════╩════╝
因为它只需要不同的值。我想要的是采用常见的行,就像:
╔═════╦════╦═══╦════╦════╗
║ A ║ B ║ C ║ D ║ E ║
╠═════╬════╬═══╬════╬════╣
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ Car ║ 10 ║ 1 ║ OK ║ -1 ║
║ Dog ║ 3 ║ 1 ║ OK ║ -1 ║
╚═════╩════╩═══╩════╩════╝
观察我不需要知道我必须链接什么(连接是位置性的,就像INTERSECT
)。 ID 将是使用所有列构建的内容(表之间的链接是所有列,基于它们的位置)。
最佳答案
在 SQL Server 中,INTERSECT
仅适用于不同的行。如果您希望它区分重复的行,则需要使行不同。我能想到的唯一方法是添加另一列并用每个重复项的唯一值填充它,但以这种方式生成的行可以在不同的表中匹配。
然而,问题是到目前为止还没有通用的语法。例如,您可以使用 ROW_NUMBER() 枚举每个重复项,但您必须为每种情况单独写出 PARTITION BY 子句:没有 PARTITION BY *,至少在 SQL Server 中没有.
无论如何,为了便于说明,ROW_NUMBER 方法如下所示:
SELECT
A, B, C, D, E,
ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1))
FROM
dbo.A
INTERSECT
SELECT
A, B, C, D, E,
ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1))
FROM
dbo.B
;
如上所述,查询还将在输出中返回一个额外的列,即行号列。如果您想抑制它,则需要使查询更复杂:
SELECT
A, B, C, D, E
FROM
(
SELECT
A, B, C, D, E,
rn = ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1))
FROM
dbo.A
INTERSECT
SELECT
A, B, C, D, E,
rn = ROW_NUMBER() OVER (PARTITION BY A, B, C, D, E ORDER BY (SELECT 1))
FROM
dbo.B
) AS s
;
为了澄清,当我上面说没有通用语法时,我的意思是如果不借助动态 SQL 就无法做到这一点。使用动态 SQL,很多事情都是可能的,但这样的解决方案会更加复杂,而且在我看来,可维护性要差得多。
再次,为了说明这一点,这是一个如何使用动态 SQL 解决该问题的示例:
DECLARE
@table1 sysname,
@table2 sysname,
@columns nvarchar(max),
@sql nvarchar(max)
;
SET @table1 = 'dbo.A';
SET @table2 = 'dbo.B';
-- collecting the columns from one table only,
-- assuming the structures of both tables are identical
-- if the structures differ, declare and populate
-- @columns1 and @columns2 separately
SET @columns = STUFF(
(
SELECT
N', ' + QUOTENAME(name)
FROM
sys.columns
WHERE
object_id = OBJECT_ID(@table1)
FOR XML
PATH (''), TYPE
).value('text()[1]', 'nvarchar(max)'),
1,
2,
''
);
SET @sql =
N'SELECT ' + @columns + N'
FROM
(
SELECT
' + @columns + N',
ROW_NUMBER() OVER (PARTITION BY ' + @columns + N' ORDER BY (SELECT 1))
FROM
' + @table1 + N'
INTERSECT
SELECT
' + @columns + N',
ROW_NUMBER() OVER (PARTITION BY ' + @columns + N' ORDER BY (SELECT 1))
FROM
' + @table2 + N'
) AS s
';
EXECUTE sp_executesql @sql;
您现在可能至少可以明白我所说的“更加复杂”是什么意思。
关于sql - SQL Server 中的相交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25921790/