Problem

首先什么是动态列表?举个示例,假设你想输出以逗号分隔的IDs,如:

1,45,67,199,298

Solution

生成动态列表数据在我们生活场景中很常见,比如在 Dynamic PIVOT中,解决方案也有许多种,小陈知道的大体有:

  • Cursor-Based

  • XML-Based

  • Set-Based  

这三种方式,性能从低到高,有兴趣的看官可以自己看一下执行计划,分析数据。这里主要演示代码和思路为主。

Cursor-Based Approach

USE AdventureWorks2014;
GO DECLARE @nextid INT;
DECLARE @myIDs NVARCHAR(MAX) = '';
DECLARE idcursor CURSOR LOCAL FAST_FORWARD
FOR
SELECT TOP 10
SalesOrderID
FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC; OPEN idcursor;
FETCH NEXT FROM idcursor INTO @nextid;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @myIDs = @myIDs + CAST(@nextid AS NVARCHAR) + N',';
FETCH NEXT FROM idcursor INTO @nextid;
END --SET @myIDs = SUBSTRING(@myIDs, 1, LEN(@myIDs) -1)
SET @myIDs = STUFF(@myIDs,LEN(@myIDs), 1, '')
SELECT @myIDs AS comma_separated_output;

分析:Cursor-Based 的思路是迭代想要的结果集,一次一次加上,最后去掉最后一个逗号。关于去掉最后一个逗号,或者刚开始的,小陈推荐使用 STUFF() 函数.

PS: 小陈觉得应该在T-SQL私房菜中加一道常见有用函数的菜谱。

XML-Based Approach

USE AdventureWorks2014;
GO DECLARE @myIDs NVARCHAR(MAX) = ''; SET @myIDs = STUFF(
(SELECT TOP 10
N',' + CAST(SalesOrderID AS NVARCHAR) AS [text()]
FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC
FOR XML PATH('')), 1, 1, '');
/*
SET @myIDs = STUFF(
(SELECT TOP 10
',' + CAST(SalesOrderID AS NVARCHAR)
FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC
FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
*/ SELECT @myIDs AS comma_separated_output;

分析:XML-Based 方式,初看之下觉得很复杂,不管怎么样,可读性上真的很差。对于看似复杂的T-SQL,小陈建议一步一步的分解,比如不了解XML AUTO PATH,可以移步MSDN查询一下。

PS:XML Reader不是免费的,在数据量大的情况下性能等同于迭代;这种方式易让别人觉得人你有奇技淫巧,一下下逼格就提高了。

Set-Based Approach

USE AdventureWorks2014;
GO DECLARE @myIDs NVARCHAR(MAX) = ''; SELECT TOP 10
@myIDs = @myIDs + N',' + CAST(SalesOrderID AS NVARCHAR)
FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC SET @myIDs = STUFF(@myIDs, 1, 1, ''); SELECT @myIDs AS comma_separated_output;

分析:Set-Based 方式,不管是从性能上,还是从可读性上,都有很大的提升,也是小陈推荐的。

彩蛋

三种方式大体可以解决我们在T-SQL常见的问题,但有时候也会掉进坑里,有些也是动态列表不能解决的。

比如我们在写SP的时候,常把IDs作为参数传进去,然后在动态SQL中:orderid in @myIDs, 现实却是很骨感的……

T-SQL Recipes之生成动态列表数据的更多相关文章

  1. ajax获取动态列表数据后的分页问题

    ajax获取动态列表数据后的分页问题 这是我在写前台网站时遇到的一个分页问题,由于数据是通过ajax的方式来请求得到的,如果引入相应的js文件来做分页,假如只是静态的填放数据到列表各项内容中(列表条数 ...

  2. 开源 免费 java CMS - FreeCMS1.9 移动APP生成网站列表数据

    项目地址:http://www.freeteam.cn/ 生成网站列表数据 提取同意移动APP訪问的网站列表,生成json数据到/mobile/index.html页面. 从左側管理菜单点击生成网站列 ...

  3. 开源 免费 java CMS - FreeCMS1.9 移动APP生成栏目列表数据

    项目地址:http://www.freeteam.cn/ 生成栏目列表数据 提取当前管理网站下同意移动APP訪问的栏目列表,生成json数据到/site/网站文件夹/mobile/channels.h ...

  4. DB2存储过程实现查询表数据,生成动态SQL,并执行

    一.动态执行SQL PREPARE S1 FROM 'delete from test'; EXECUTE S1; 二.使用游标 DECLARE V_CURSOR CURSOR FOR SELECT ...

  5. Excel 数据导入SQL XML 自动生成表头

    去出差的时候应客户要求要要将Excel 文件内的数据批量导入到数据库中,而且有各种不同种类的表格,如果每一个表格多对应一个数据表的话, 按照正常的方法应该是创建数据表,创建数据库中映射的数据模型,然后 ...

  6. 【转】Hibernate利用@DynamicInsert和@DynamicUpdate生成动态SQL语句

    原文链接:http://www.cnblogs.com/quanyongan/p/3152290.html 最近在使用Hibernate4中,发现两个很有奥秘的注解 @DynamicInsert 和  ...

  7. Hibernate利用@DynamicInsert和@DynamicUpdate生成动态SQL语句

    最近在使用Hibernate4中,发现两个很有奥秘的注解 @DynamicInsert 和 @DynamicUpdate 如果是在配置文件的话那就是dynamic -insert 和 dynamic- ...

  8. ASP.NET实现二维码 ASP.Net上传文件 SQL基础语法 C# 动态创建数据库三(MySQL) Net Core 实现谷歌翻译ApI 免费版 C#发布和调试WebService ajax调用WebService实现数据库操作 C# 实体类转json数据过滤掉字段为null的字段

    ASP.NET实现二维码 using System;using System.Collections.Generic;using System.Drawing;using System.Linq;us ...

  9. 在论坛中出现的比较难的sql问题:15(生成动态删除列语句 分组内多行转为多列)

    原文:在论坛中出现的比较难的sql问题:15(生成动态删除列语句 分组内多行转为多列) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路. 1.如果去掉这个临时表中合计为0 ...

随机推荐

  1. ubuntu下安装gedit插件

    因为gedit-plugins : 依赖: gir1.2-zeitgeist-2.0 所以首先 sudo apt-get install gir1.2-zeitgeist-2.0 如果报错可以先 su ...

  2. python程序一直在后台运行的解决办法

    刚写了个python程序,要一直在后台运行,即使断开ssh进程也在,下面是解决办法: 假如Python程序为test.py 编写shell脚本start.sh #!/bin/bash python t ...

  3. sobel算子的一些细节

    1. 形式 Gy 上下颠倒的 (*A表示卷积图像,忽略先): 看得出来,sobel算子感觉并不统一,特别是方向,我们知道matlab的图像格式是,x轴从左到右,y轴从上到下,原点在左上角. 所以,第二 ...

  4. ActiveMQ 即时通讯服务 浅析

      一. 概述与介绍 ActiveMQ 是Apache出品,最流行的.功能强大的即时通讯和集成模式的开源服务器.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provi ...

  5. Firefox 及其 插件“个性化设置”备份

    Firefox版本发布时间表 2016.10.22 49.0.2 2016.11.15 50.0 2016.11.08 重新使用 Firefox(版本为 49.0.2),访问 Firefox官网 常用 ...

  6. 商品库存“存取设计”,MySQL事务、表锁、行锁

    MySQL  使用 SELECT ... FOR UPDATE 做事务写入前的确认 以MySQL 的InnoDB 为例,预设的 Tansaction isolation level 为 REPEATA ...

  7. Shell入门教程:Shell函数的返回值

    shell函数返回值一般有3种方式: 1.return语句(默认的返回值) shell函数的返回值可以和其他语言的返回值一样,通过return语句返回. 比如: #!/bin/bash functio ...

  8. MFC在关闭第二个窗口时关闭主对话框

    AfxGetApp()->m_pMainWnd->SendMessage(WM_CLOSE);//关闭主对话框

  9. jquery解析php通过ajax传过来的json二维数组对象

    ajax获得php传过来的json二维数组对象,jquery解析 php代码: <?php $news = array( '武汉'=>array(1,2,3), '广州'=>arra ...

  10. 十一. 一步步破解JEB 2.0demo版一

    字符串解密算法还愿 jeb.jar为核心功能,所以主要分析这个 1. jar转dex在使用jeb分析 Android\sdk\build-tools\23.0.3 dx.bat --dex --out ...