Sql server TSQL:通过对值进行分组和连接来合并两个集合

Sql server TSQL:通过对值进行分组和连接来合并两个集合,sql-server,tsql,Sql Server,Tsql,我有两个表,每个表中有200多万行。我需要合并它们,性能非常重要 合并后需要连接这些标志 表1 表2 表3-两个表上的合并标志 ip flags ----------- 23.4.2.8 yx -- merged flags, the order of flags is not important 94.4.7.3 t -- merged flags, but distinct 12.5.7.9 x 33.1.2.3 xc 99.6.7.9 t 我用C语言编写了这个

我有两个表,每个表中有200多万行。我需要合并它们,性能非常重要

合并后需要连接这些标志

表1

表2

表3-两个表上的合并标志

ip       flags
-----------
23.4.2.8  yx  -- merged flags, the order of flags is not important
94.4.7.3  t   -- merged flags, but distinct
12.5.7.9  x
33.1.2.3  xc
99.6.7.9  t

我用C语言编写了这个程序,不知道是否可以用SQL来实现。是否有一个SQL命令可以有效地执行此操作?

您没有提到您使用的是哪个版本的SQL Server,但如果是2017+版本,此解决方案将适用于您。 您可以使用STRING_AGG实现您的目标。使用您的数据尝试以下操作:根据上面的示例数据创建表

CREATE TABLE #table1(
    ip VARCHAR(100)
    ,flags CHAR(10)
)
GO
CREATE TABLE #table2(
    ip VARCHAR(100)
    ,flags CHAR(10)
)
GO

INSERT INTO #table1 VALUES 
('23.4.2.8','x')
,('94.4.7.3','t')
,('12.5.7.9','x')
,('33.1.2.3','xc')
GO 

INSERT INTO #table2 VALUES 
 ('23.4.2.8','y')
,('94.4.7.3','t')
,('99.6.7.9','t')

GO 

SELECT 
    ip
    ,STRING_AGG(RTRIM(flags),',')
FROM
(
    SELECT 
        ip
        ,flags 
    FROM #table1
    UNION ALL
    SELECT 
        ip
        ,flags 
    FROM #table2
)a
GROUP BY ip


您没有提到您正在使用哪个版本的SQL Server,不过如果是2017+的话,这个解决方案将适合您。 您可以使用STRING_AGG实现您的目标。使用您的数据尝试以下操作:根据上面的示例数据创建表

CREATE TABLE #table1(
    ip VARCHAR(100)
    ,flags CHAR(10)
)
GO
CREATE TABLE #table2(
    ip VARCHAR(100)
    ,flags CHAR(10)
)
GO

INSERT INTO #table1 VALUES 
('23.4.2.8','x')
,('94.4.7.3','t')
,('12.5.7.9','x')
,('33.1.2.3','xc')
GO 

INSERT INTO #table2 VALUES 
 ('23.4.2.8','y')
,('94.4.7.3','t')
,('99.6.7.9','t')

GO 

SELECT 
    ip
    ,STRING_AGG(RTRIM(flags),',')
FROM
(
    SELECT 
        ip
        ,flags 
    FROM #table1
    UNION ALL
    SELECT 
        ip
        ,flags 
    FROM #table2
)a
GROUP BY ip


如果您没有使用STUFF和FOR XML PATH的SQL Server 2017+的另一个选项,我认为这对2008年很好+

这里有一个


如果您没有使用STUFF和FOR XML PATH的SQL Server 2017+的另一个选项,我认为这对2008年很好+

这里有一个


不确定您的桌子有多宽,但下面类似的方法可以工作:

SELECT ISNULL(t.IP, t2.IP) AS IP
    , CONCAT(ISNULL(t.flags,’’), ISNULL(t2.flags, ‘’)) AS flags
FROM table1 as t
FULL JOIN table2 as t2 ON t.IP = t2.IP

不确定您的桌子有多宽,但下面类似的方法可以工作:

SELECT ISNULL(t.IP, t2.IP) AS IP
    , CONCAT(ISNULL(t.flags,’’), ISNULL(t2.flags, ‘’)) AS flags
FROM table1 as t
FULL JOIN table2 as t2 ON t.IP = t2.IP

通过ssn扩展答案以清除重复字符。 表演真的很好

SELECT ISNULL(t.IP, t2.IP) AS IP
    , [dbo].[FN_CLEANDUPCHAR](CONCAT(ISNULL(t.block_reason_code,''), ISNULL(t2.block_reason_code, ''))) AS block_reason_code 
FROM ##table1 as t FULL JOIN ##table2 as t2 
ON t.IP = t2.IP
这就是功能:

CREATE FUNCTION [dbo].[FN_CLEANDUPCHAR]
(
    @S varchar(20)
)
RETURNS varchar(20)
AS
BEGIN
    SELECT
        @S = CASE WHEN CHARINDEX(SUBSTRING(@s,Number,1),@s) BETWEEN 1 AND Number-1 THEN STUFF(@s,Number,1,'') ELSE @S END
    FROM master.dbo.spt_values
    WHERE Number BETWEEN 2 AND LEN(@s) AND type='P'
    ORDER BY Number DESC

    return @S    
END
GO

通过ssn扩展答案以清除重复字符。 表演真的很好

SELECT ISNULL(t.IP, t2.IP) AS IP
    , [dbo].[FN_CLEANDUPCHAR](CONCAT(ISNULL(t.block_reason_code,''), ISNULL(t2.block_reason_code, ''))) AS block_reason_code 
FROM ##table1 as t FULL JOIN ##table2 as t2 
ON t.IP = t2.IP
这就是功能:

CREATE FUNCTION [dbo].[FN_CLEANDUPCHAR]
(
    @S varchar(20)
)
RETURNS varchar(20)
AS
BEGIN
    SELECT
        @S = CASE WHEN CHARINDEX(SUBSTRING(@s,Number,1),@s) BETWEEN 1 AND Number-1 THEN STUFF(@s,Number,1,'') ELSE @S END
    FROM master.dbo.spt_values
    WHERE Number BETWEEN 2 AND LEN(@s) AND type='P'
    ORDER BY Number DESC

    return @S    
END
GO

表1中33.1.2.3上的两个标志xc是否需要明确处理?我的意思是,如果表2有33.1.2.3->x,表3会有33.1.2.3->xxc还是33.1.2.3->xc?33.1.2.3会保持xc。。。标志不同表1中33.1.2.3中的两个标志xc是否需要进行明确处理?我的意思是,如果表2有33.1.2.3->x,表3会有33.1.2.3->xxc还是33.1.2.3->xc?33.1.2.3会保持xc。。。旗帜很明显,很不幸,这对我不起作用。我们的SQL兼容度为130,版本为13.0…@realPro我曾考虑过XML路径方法,尽管STRING_AGG要优雅得多,我不确定您使用的是哪个版本。BJones提供的答案似乎是我在String_Agg之前应该做的,谢谢,不幸的是这对我不起作用。我们的SQL兼容度为130,版本为13.0…@realPro我曾考虑过XML路径方法,尽管STRING_AGG要优雅得多,我不确定您使用的是哪个版本。BJones提供的答案似乎是我在使用String_之前应该做的,谢谢!这真的很快!请参阅我发布的答案和您的代码。谢谢!这真的很快!请参阅我发布的答案和您的代码。