在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;

后面测试发现,当组合的字符串数量超过或等于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 Server如何用SQL实现一批字符串的全部组合的更多相关文章

  1. SQL Server 2012:SQL Server体系结构——一个查询的生命周期(第2部分)

    计划缓存(Plan Cache) 如果SQL Server已经找到一个好的方式去执行一段代码时,应该把它作为随后的请求重用,因为生成执行计划是耗费时间且资源密集的,这样做是有有意义的. 如果没找到被缓 ...

  2. SQL SERVER如何通过SQL语句获服务器硬件和系统信息

    在SQL SERVER中如何通过SQL语句获取服务器硬件和系统信息呢?下面介绍一下如何通过SQL语句获取处理器(CPU).内存(Memory).磁盘(Disk)以及操作系统相关信息.如有不足和遗漏,敬 ...

  3. Comparison of SQL Server Compact, SQLite, SQL Server Express and LocalDB

    Information about LocalDB comes from here and SQL Server 2014 Books Online. LocalDB is the full SQL ...

  4. SQL Server:查看SQL日志文件大小命令:dbcc sqlperf(logspace)

      SQL Server:查看SQL日志文件大小命令:dbcc sqlperf(logspace) DBA 日常管理工作中,很重要一项工作就是监视数据库文件大小,及日志文件大小.如果你管理数据库的有很 ...

  5. SQL Server 2012:SQL Server体系结构——一个查询的生命周期(第1部分)

    为了缩小读取操作所涉及范围,本文首先着眼于简单的SELECT查询,然后引入执行更新操作有关的附加过程.最后你会读到,优化性能时SQLServer使用还原工具的相关术语和流程. 关系和存储引擎 如图所示 ...

  6. [Microsoft][ODBC SQL Server Driver][DBNETLIB]SQL Server 不存在或访问被拒绝

    一般连接sql数据库,IP_connstr="driver={SQL Server}; server=127.0.0.1;database=数据库名字;uid=sa;pwd=密码" ...

  7. SQL Server 127个SQL server热门资料汇总

      SQL Server 127个SQL server热门资料汇总     最近有许多关于如何学习SQLSERVER的问题,其实新手入门的资源和贴子很多,现在向大家隆重推荐经过精心整理的[SQLSer ...

  8. 如何启动 SQL Server Agent(SQL Server 配置管理器)

    如何启动 SQL Server Agent(SQL Server 配置管理器) SQL Server 2008 R2 其他版本   4(共 6)对本文的评价是有帮助 - 评价此主题 可以从 SQL S ...

  9. SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表)

    原文:SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表) 作为SQL Server 2016(CTP3.x)的另一 ...

随机推荐

  1. intellij idea maven project 无法显示dependencies

    Intellj 自动载入Mave依赖是一个很人性化的功能,但不排除有时候会碰到问题,导致pom文件修改却没有触发自动重新载入的动作或者加载中途出现弱网的情况中断载入的,此时需要手动强制更新依赖. 如下 ...

  2. python args kwargs 传递参数的区别

    先来看个例子: def foo(*args, **kwargs): print 'args = ', args print 'kwargs = ', kwargs print '----------- ...

  3. [转]Memcache的使用和协议分析详解

    Memcache是什么 Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力. 它可以应 ...

  4. 痞子衡嵌入式:恩智浦半导体全系无线(BLE, Zigbee, Thread, 2.4G, Sub-1G)微控制器芯片一览

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦半导体全系列无线微控制器芯片. IoT物联网是未来的趋势,半导体厂商作为IoT产业的上游,主要提供核心的无线芯片,作为半导体知名厂 ...

  5. .net DBHelper

    DBHelper.cs是程序来连接数据的,也是一个程序必不可少的一个类(本人道行浅,目前这样认为).由于一个程序基本写一次,容易忘记.所有写在这里备注 首先是引用 using System.Data; ...

  6. “笨方法”学习Python笔记(2)-VS Code作为文本编辑器以及配置Python调试环境

    Visual Studio Code 免费跨平台文本编辑器,插件资源丰富,我把其作为Debug的首选. 下载地址:https://code.visualstudio.com/Download 安装之后 ...

  7. 未能加载文件或程序集 Microsoft.ReportViewer.ProcessingObjectModel, Version=10.0.0.0…错误问题的解决

    1.分析原因: 出现未能加载文件或程序集 Microsoft.ReportViewer.ProcessingObjectModel, Version=10.0.0.0的问题的原因是,Microsoft ...

  8. 解决命名空间“System.Web.Mvc”中不存在类型或命名空间名称“Ajax”(是否缺少程序集引用?)

    解决命名空间“System.Web.Mvc”中不存在类型或命名空间名称“Ajax”(是否缺少程序集引用?) 1.右击引用中的System.Web.MVC,点击“属性” 把"复制本地" ...

  9. T-SQL基础(六)之可编程对象

    变量 -- 声明变量 DECLARE @variable_name [AS] variable_type; -- 变量赋值 SET @variable_name = variable_value; 示 ...

  10. Netty实战八之引导

    通过前面的学习,我们可能要考虑一个问题:如何将这些部分组织起来,成为一个可实际运行的应用程序呢? 答案是引导.简单来说,引导一个应用程序是指对它进行配置,并使它运行起来的过程——尽管该过程的具体细节可 ...