TSQL:合并两个集合,对值进行分组和串联

时间:2019-12-04 19:15:15

标签: sql-server tsql

我有两个表,每个表有2+百万行。我需要将它们合并,性能非常重要。

合并后需要将这些标志串联起来。

表1

ip       flags
-----------
23.4.2.8  x
94.4.7.3  t
12.5.7.9  x
33.1.2.3  xc

表2

ip       flags
-----------
23.4.2.8  y
94.4.7.3  t
99.6.7.9  t

表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命令可以有效地做到这一点?

4 个答案:

答案 0 :(得分:2)

如果您没有使用STUFFFOR XML PATH()的SQL Server 2017+,则可以选择另一种方法-我认为这对于2008年+来说是不错的选择

这里是SQL Fiddle

SELECT 
    ip
    ,STUFF((SELECT  ',' + t.flags
            FROM(
                SELECT ip, flags 
                FROM table1
                UNION ALL
                SELECT ip, flags 
                FROM table2
                )t
            WHERE t.ip = a.ip
        FOR XML PATH('')), 1, 1, '') AS Flags
FROM
(
    SELECT ip, flags 
    FROM table1
    UNION ALL
    SELECT ip, flags 
    FROM table2
)a
GROUP BY ip

答案 1 :(得分:1)

您没有提到您使用的是哪个版本的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

答案 2 :(得分:1)

不确定表格的宽度,但是下面的方法可能起作用:

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

答案 3 :(得分:0)

通过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