SQL Server如何用SQL实现一批字符串的全部组合

简介: 原文:SQL Server如何用SQL实现一批字符串的全部组合在SQL Server中,如何用SQL去实现得到一批字符串的全部组合呢?这个是同事在实际需求当中遇到的一个问题,他的具体需求如下所示:   传入参数格式为'1,2,3,224,15,6'   'A,BC,GHT,TTY,B,E' ...
原文: SQL Server如何用SQL实现一批字符串的全部组合

在SQL Server中,如何用SQL去实现得到一批字符串的全部组合呢?这个是同事在实际需求当中遇到的一个问题,他的具体需求如下所示:

 

传入参数格式为'1,2,3,224,15,6'   'A,BC,GHT,TTY,B,E'

 

输出的内容为分割后字符串的所有非排列组合

!-阶乘,如!=5××××=120  (M!/(N!*((M-N)!)))  

 

公式描述:组合数公式是从m个不同元素中,任取n(n≤m)个元素并成一组,叫做从m个不同元素中取出n个元素的一个组合;

从m个不同元素中取出n(n≤m)个元素的所有组合的个数,叫做从m个不同元素中取出n个元素的组合数。用符号c(m,n) 表示。

如果有5个数字那么就是M=5  单个数字组合N=1   (M!/(N!*((M-N)!)))=5   

                    是M=5  2个数字组合N=2    (M!/(N!*((M-N)!)))=10

                    是M=5  3个数字组合N=3    (M!/(N!*((M-N)!)))=10

                    是M=5  4个数字组合N=4    (M!/(N!*((M-N)!)))=5

                    是M=5  5个数字组合N=5    (M!/(N!*((M-N)!)))=1   

可能全部的组合有 10 + 10 + 5+ 5 + 1 =31 种。传入的参数分割后越多,组合数也就越庞大。

 

             

他最开始的实现方式就是用多层循环实现(此处就不贴代码了),但是当要实现组合的字符串数量增多时,效率性能就下降得非常厉害,后面我参考一种写法写了下面SQL语句。

--创建辅助表SEQ_NUMBER
CREATE TABLE SEQ_NUMBER(COL_NUM INT);
DECLARE @Index INT =1;
 
WHILE @Index <=32
BEGIN
    INSERT INTO SEQ_NUMBER VALUES(@Index);
 
    SET @Index +=1;
END;
GO
 
 
--创建辅助表,用于保存拆分后的字符串
CREATE TABLE SplitString(COL_NUM INT IDENTITY(1,1) ,VAL  VARCHAR(32));
 
 
--创建函数
CREATE FUNCTION FN_GET_COMBINATIONS()
RETURNS @OutTable TABLE(COL VARCHAR(32), VAL  VARCHAR(32))
AS
BEGIN
    DECLARE @Str  VARCHAR(32)='';
    DECLARE @Index INT =1;
    DECLARE @RowCount INT;
 
    SELECT @RowCount=COUNT(*) FROM SplitString;
 
    
    --注意,如果字符串分隔后有5个字符串(A,BC,GHT,TTY,B,E),就使用12345, 如果分割后有6个字符串,就必须用123456,以此类推
    WHILE @Index <= @RowCount
        BEGIN
 
            SET @Str = @Str + CAST(@Index AS VARCHAR(2))
            SET @Index = @Index +1
        END
 
    INSERT INTO @OutTable
    SELECT   S.COL_NUM, T.VAL FROM SEQ_NUMBER S , SplitString T
    WHERE S.COL_NUM = T.COL_NUM ORDER BY T.COL_NUM;
 
    WHILE NOT EXISTS(SELECT 1 FROM @OutTable where COL = @Str)
    INSERT INTO @OutTable
    SELECT T3.COL + T2.COL, T3.VAL + T2.VAL FROM @OutTable AS T2,@OutTable AS T3 WHERE len(t3.col) = 1 and charindex(T3.COL,T2.COL) =0 and T2.COL > T3.COL
 
    RETURN;
END

 

然后假如,我们需要实现字符串'1,2,3,4,5'中1,2,3,4,5的所有组合方式,那么我们用下面SQL就能得到结果。如下所示,当然你也可以用诸如'A,BC,GHT,TTY,B,E'这样的字符串去获取字符串的所有组合。

 

DECLARE @String VARCHAR(200)
DECLARE @SqlText VARCHAR(MAX)
DECLARE @Index INT=1;
 
SET @String='A,BC,GHT,TTY,B';
SET @SqlText='SELECT COL='''+ REPLACE(@STRING,',',''' UNION ALL SELECT ''')+''''
 
 
--清空旧数据,保存需要进行组合的字符串数据。
TRUNCATE TABLE SplitString;
 
 
INSERT INTO SplitString
EXEC (@SqlText)
 
 
 
 
SELECT DISTINCT
        CHAR_VAL ,
        COL_NUM ,LEN(COL_NUM) AS STR_CNT 
FROM    dbo.FN_GET_COMBINATIONS()
WHERE   LEN(COL_NUM) >= 1
ORDER BY LEN(COL_NUM) ,COL_NUM;

clipboard

 

后面测试发现,当组合的字符串数量超过或等于10个时,这个函数就有问题了(有兴趣的可以自行测试,例如传入的参数为’1,2,3,4,5,6,7,8,9,10’)。所以又对这个进行了一番修改。目前最多支持获取26个字符串的全部组合,这个已经完全满足业务需要了。如果再需要跟多的字符串组合,则还需修改函数。这个函数效率也是与需要组合的字符串个数有相关,如果组合11个字符串,基本上需要3~4秒的时间,如果组合的字符串个数越多,则所需时间越多。当然,如果组合的字符串个数7~8个,几乎就是1秒内。

 

CREATE TABLE SEQ_CHARACTER(COL_NUM INT ,COL_CHAR VARCHAR(36));
 
INSERT INTO SEQ_CHARACTER
SELECT 1 ,'A' UNION ALL
SELECT 2 ,'B' UNION ALL
SELECT 3 ,'C' UNION ALL
SELECT 4 ,'D' UNION ALL
SELECT 5 ,'E' UNION ALL
SELECT 6 ,'F' UNION ALL
SELECT 7 ,'G' UNION ALL
SELECT 8 ,'H' UNION ALL
SELECT 9 ,'I' UNION ALL
SELECT 10,'J' UNION ALL
SELECT 11,'K' UNION ALL
SELECT 12,'L' UNION ALL
SELECT 13,'M' UNION ALL
SELECT 14,'N' UNION ALL
SELECT 15,'O' UNION ALL
SELECT 16,'P' UNION ALL
SELECT 17,'Q' UNION ALL
SELECT 18,'R' UNION ALL
SELECT 19,'S' UNION ALL
SELECT 20,'T' UNION ALL
SELECT 21,'U' UNION ALL
SELECT 22,'V' UNION ALL
SELECT 23,'W' UNION ALL
SELECT 24,'X' UNION ALL
SELECT 25,'Y' UNION ALL
SELECT 26,'Z'
 
 
CREATE TABLE SplitString(COL_NUM INT IDENTITY(1,1) ,VAL  VARCHAR(32));
 
 
 
CREATE FUNCTION FN_GET_COMBINATIONS()
RETURNS @OutTable TABLE(COL_NUM VARCHAR(32), CHAR_VAL  VARCHAR(32))
AS
BEGIN
    DECLARE @Str  VARCHAR(32)='';
    DECLARE @Index INT =1;
    DECLARE @RowCount INT;
 
    SELECT @RowCount=COUNT(*) FROM SplitString;
 
    
    --注意,如果字符串分隔后有5个字符串(A,BC,GHT,TTY,B,E),就使用12345, 如果分割后有6个字符串,就必须用123456,以此类推
    WHILE @Index <= @RowCount
        BEGIN
 
            SELECT  @Str = @Str + LTRIM(RTRIM(COL_CHAR)) FROM SEQ_CHARACTER WHERE COL_NUM=@Index
            SET @Index = @Index +1
        END
 
    INSERT INTO @OutTable
    SELECT   S.COL_CHAR, T.VAL FROM SEQ_CHARACTER S , SplitString T
    WHERE S.COL_NUM = T.COL_NUM ORDER BY T.COL_NUM;
 
    WHILE NOT EXISTS(SELECT 1 FROM @OutTable where COL_NUM = @Str)
    INSERT INTO @OutTable
    SELECT T3.COL_NUM + T2.COL_NUM, T3.CHAR_VAL + T2.CHAR_VAL FROM @OutTable AS T2,@OutTable AS T3 WHERE len(T3.COL_NUM) = 1 and charindex(T3.COL_NUM,T2.COL_NUM) =0 and T2.COL_NUM > T3.COL_NUM
 
    RETURN;
END

 

测试脚本如下:

 

DECLARE @String VARCHAR(200)
DECLARE @SqlText VARCHAR(MAX)
DECLARE @Index INT=1;
 
SET @String='A,B,C,D,E,F,G,H,G,H,I';
SET @SqlText='SELECT COL='''+ REPLACE(@STRING,',',''' UNION ALL SELECT ''')+''''
 
 
--清空旧数据,保存需要进行组合的字符串数据。
TRUNCATE TABLE SplitString;
 
 
INSERT INTO SplitString
EXEC (@SqlText)
 
 
 
 
SELECT DISTINCT
        CHAR_VAL ,
        COL_NUM ,LEN(COL_NUM) AS STR_CNT 
FROM    dbo.FN_GET_COMBINATIONS()
WHERE   LEN(COL_NUM) >= 1
ORDER BY LEN(COL_NUM) ,COL_NUM;
目录
相关文章
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
2095 0
|
SQL Web App开发 安全
SQL Server 2025 年 8 月更新 - 修复 CVE-2025-49759 SQL Server 特权提升漏洞
SQL Server 2025 年 8 月更新 - 修复 CVE-2025-49759 SQL Server 特权提升漏洞
1436 2
SQL Server 2025 年 8 月更新 - 修复 CVE-2025-49759 SQL Server 特权提升漏洞
|
SQL Web App开发 安全
SQL Server 2025 年 9 月更新 - 修复 CVE-2025-47997 SQL Server 信息泄露漏洞
SQL Server 2025 年 9 月更新 - 修复 CVE-2025-47997 SQL Server 信息泄露漏洞
769 0
SQL Server 2025 年 9 月更新 - 修复 CVE-2025-47997 SQL Server 信息泄露漏洞
|
SQL 容灾 安全
云时代SQL Server的终极答案:阿里云 RDS SQL Server如何用异地容灾重构系统可靠性
在数字化转型的浪潮中,数据库的高可用性已成为系统稳定性的生命线。作为经历过多次生产事故的资深开发者,肯定深知传统自建SQL Server架构的脆弱性——直到遇见阿里云 RDS SQL Server,其革命性的异地容灾架构彻底改写了游戏规则。
|
SQL Web App开发 安全
SQL Server 2025年7月更新 - 修复 CVE-2025-49718 Microsoft SQL Server 信息泄露漏洞
SQL Server 2025年7月更新 - 修复 CVE-2025-49718 Microsoft SQL Server 信息泄露漏洞
1387 0
SQL Server 2025年7月更新 - 修复 CVE-2025-49718 Microsoft SQL Server 信息泄露漏洞
|
SQL 数据库
执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.ConnectionInfo)之解决方案
执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.ConnectionInfo)之解决方案
2247 1
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
SQL Oracle 关系型数据库
SQL语句中的引号使用技巧:正确处理字符串与标识符
在编写SQL语句时,引号的使用是一个基础且重要的环节
2678 0
|
SQL 关系型数据库 MySQL
MySQL根据某个字段包含某个字符串或者字段的长度情况更新另一个字段的值,如何写sql
MySQL根据某个字段包含某个字符串或者字段的长度情况更新另一个字段的值,如何写sql
951 0
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1796 152