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. thinkphp3.2与phpexcel带图片生成 完美案例

    thinkphp3.2与phpexcel完美案例 // 导出exl public function look_down(){ $id = I('get.id'); $m = M ('offer_goo ...

  2. 清北学堂模拟赛day7 石子合并加强版

    /* 注意到合并三堆需要枚举两个端点,其实可以开一个数组记录合并两堆的结果,标程好像用了一个神奇的优化 */ #include<iostream> #include<cstdio&g ...

  3. JSP脚本中的9个内置对象

    JSP脚本中包含9个内置对象,这9个内置对象都是Servlet API接口的实例,只是JSP规范对它们进行了默认初始化.也就是说它们已经是对象,可以直接使用. 我们随意打开一个由JSP页面生成的Ser ...

  4. [Hadoop] 在Ubuntu系统上一步步搭建Hadoop(单机模式)

    1 Hadoop的三种创建模式 单机模式操作是Hadoop的默认操作模式,当首次解压Hadoop的源码包时,Hadoop无法了解硬件安装环境,会保守地选择最小配置,即单机模式.该模式主要用于开发调试M ...

  5. shell--2.shell数组

    shell 数组 (1)定义数组 shell中,用括号表示数组,数组元素用空格分开,定义数组的一般形式 arrt_name=(val1 val2 val3) 或者 arry_name=(val1 va ...

  6. LwIP移植和使用

    LwIP移植和使用 本手册基于lwip-1.4.x编写,本人没有移植过1.4.0之前的版本,更早的版本或许有差别.如果看官发现问题欢迎联系<QQ: 937431539  email: 93743 ...

  7. C/C++ 笔试题

    /////转自http://blog.csdn.net/suxinpingtao51/article/details/8015147#userconsent# 微软亚洲技术中心的面试题!!! 1.进程 ...

  8. 用JS做关灯游戏(初级)

    这是一个很有意思的游戏,可以试着玩下. <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  9. [Keygen]IntelliJ IDEA 14.1.7

    IntelliJ IDEA 14.1.7 Keygen package com.candy.keygen.intelliJIdea; import java.math.BigInteger; impo ...

  10. alert 替代效果smoke.js

    在一些表单等需要弹窗提醒的时候,每个浏览器都有一个alert(),comfirm()函数能弹出信息,但是浏览器的自带的这种效果样式不统一,而且都固定在页面顶部: smoke.js轻量级的JS插件,他标 ...