Reputation: 1846
I have two tables with 2+ million rows in each. I need to merge them and the performance is very important.
The flags need to get concatenated after merge.
Table 1
ip flags
-----------
23.4.2.8 x
94.4.7.3 t
12.5.7.9 x
33.1.2.3 xc
Table 2
ip flags
-----------
23.4.2.8 y
94.4.7.3 t
99.6.7.9 t
Table 3 - merged flags on both tables
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
I have this working in C# and wonder if it is possible to do this using SQL. Is there a SQL command that can do this in efficient way?
Upvotes: 1
Views: 79
Reputation: 1846
Expanding the answer by ssn to clean the duplicate characters. The performance is really good!
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
And this is the function:
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
Upvotes: 0
Reputation: 509
Not sure how wide your tables are, but something like below could work:
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
Upvotes: 1
Reputation: 2460
Another option if you don't have SQL Server 2017+ using STUFF
and FOR XML PATH()
- I think it's good for 2008 +
Here's a 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
Upvotes: 2
Reputation: 2608
You didn't mention which version of SQL Server you're using, though if it is 2017+ this solution will work for you.
You can accomplish your goal using STRING_AGG
. Try the following with your data (create tables based off of your sample data above)
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
Upvotes: 1