gpt4 book ai didi

sql - SQL Server 中的相交

转载 作者:行者123 更新时间:2023-12-03 00:00:06 26 4
gpt4 key购买 nike

有没有一种方法可以使用 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com