zoukankan      html  css  js  c++  java
  • sql server的for xml path与变通的行转列

    SQL Server中有提供一个FOR XML PATH的子句(不知道能不能叫函数),用来将查询结果行输出成XML格式,我们可以通过这个语法做一些变通实现一些特定的功能,比如说行转列。要会变通的话,当然首先是要知道FOR XML PATH的语法。

    FOR XML PATH的简单语法

    假设有一个hobby表(爱好),表中有两个字段,一个是hobbyID(爱好id),一个是hName(爱好名称)。

    这样,我们执行一条最简单的带FOR XML PATH子句的SQL语句,看看查询出来的结果。

    SELECT * FROM hobby FOR XML PATH;
    <row>
      <hobbyID>1</hobbyID>
      <hName>爬山</hName>
    </row>
    <row>
      <hobbyID>2</hobbyID>
      <hName>游泳</hName>
    </row>
    <row>
      <hobbyID>3</hobbyID>
      <hName>美食</hName>
    </row>

    由结果可见FOR XML PATH子句可以将查询结果行输出成XML格式。

    FOR XML PATH的变通

    更多的,FOR XML PATH子句是支持传递参数的,即FOR XML PATH(schema),这样的话在查询的时候就会将行标签<row>替换为<schema>,要注意的是schema必须是字符串。

    SELECT * FROM hobby FOR XML PATH('yanggb');
    <yanggb>
      <hobbyID>1</hobbyID>
      <hName>爬山</hName>
    </yanggb>
    <yanggb>
      <hobbyID>2</hobbyID>
      <hName>游泳</hName>
    </yanggb>
    <yanggb>
      <hobbyID>3</hobbyID>
      <hName>美食</hName>
    </yanggb>

    这时候,就可以利用XML的特点,即空标签不会存在的特定,将行标签<row>去掉。

    SELECT * FROM hobby FOR XML PATH('');
    <hobbyID>1</hobbyID>
    <hName>爬山</hName>
    <hobbyID>2</hobbyID>
    <hName>游泳</hName>
    <hobbyID>3</hobbyID>
    <hName>美食</hName>

    那能更改/去除行标签<row>,能不能更改/去除列标签呢?答案是可以的,可以通过给列起别名的方式来更改/除列标签。要注意的是这里的别名也必须是字符串。

    SELECT hobbID AS AA, hName AS BB FROM hobby FOR XML PATH('');
    <AA>1</AA>
    <BB>爬山</BB>
    <AA>2</AA>
    <BB>游泳</BB>
    <AA>3</AA>
    <BB>美食</BB>

    与去除行标签<row>的方式不一样的是,去除列标签不能将别名定义为空字符串,否则数据库引擎会报错误:[Err] 42000 - [SQL Server]缺少对象或列名,或者对象或列名为空。对于 SELECT INTO 语句,请确保每列均具有名称。对于其他语句,请查找空的别名。不允许使用定义为 "" 或 [] 的别名。请将别名更改为有效名称。

    那么要怎么去除列标签呢,做法是给字段加上空字符串(加任何字符串都可以,我的理解是这种做法修改了列值,在没有起别名的情况下,原来的列标签不再匹配列值,数据库引擎会将自动该列标签去除)。

    SELECT hobbID + '', hName + '' FROM hobby FOR XML PATH('');
    1爬山2游泳3美食

    FOR XML PATH实现行转列

    根据上面的FOR XML PATH的变通的内容,我们就可以来实现行转列了。

    SELECT
        hName, 
        (SELECT ',' + hName FROM hobby FOR XML PATH('')) AS hNames
    FROM hobby FOR XML PATH('');

    这样我们就能得到一个所有爱好拼接起来的列hNames。

    这时候我们会发现hNames字段值多了一个逗号,使用STUFF函数(推荐)或REPLACE函数去除即可。

    更多的,可以在FOR XML PATH子句前添加WHERE子句限定条件范围来限定行转列的范围(也可以使用自连接限定当前行转列的范围)。

    当然了,SQL SERVER还提供了另外的行转列的PRIVOT函数和列转行的UNPRIVOT函数。

    "一个姑娘不会因为你专一痴情就喜欢你,只会因为你优秀而喜欢你。"

  • 相关阅读:
    nginx反向代理配置根据User-Agent跳转m站
    Windows环境下安装Redis
    Python的requests、greenlet和gevent模块在windows下安装
    zabbix-agent报错:zabbix_agentd [5922]: cannot open log: cannot create semaphore set: [28] No space left on device
    aws存储桶s3使用
    使用云负载时将http的请求转发至https时报错:“ERR_TOO_MANY_REDIRECTS”!
    使用CDN后配置nginx自定义日志获取访问用户的真实IP
    自动化运维工具saltstack05 -- 之salt-ssh模式
    CentOS7.2下配置SOCKS5代理
    Arch Linux 硬盘引导-联网安装
  • 原文地址:https://www.cnblogs.com/yanggb/p/11024487.html
Copyright © 2011-2022 走看看