sql多行多列重复
在sql的查询中我们会遇到查询的结果比如这样的:
查询这张表的sql语句:
select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID

就拿钱三行来说就一个ROLE_NAME不一样其他的列的数值都是一样的难道我们就要这样的结果,就算我们要这样的结果但是当我们想要在前台这样显示一个页面的时候我们怎么办

这样的话我们该怎么去查询该怎么组合,把它分开来查询当然也能解决,但是想想那样我们要查询多少次要连接数据库对少次。
这样想想就觉得很麻烦当然想想也知道这样做肯定是降低了程序的执行效率。所以我们就应该想另一种方法怎样查询一次就可以变成这种效果。
想想看我们查询的结果是一张表那我们就看这张表的XML文件的组成是什么样的
查看表的组成的XML文件的sql语句:
select * from (select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t for XML path
查出表的XML文件的组成
想想看如果我们可以替换XML文件的组成的话我们是不是就可以改变表的结构了
我们先看一个简单的表,多行的重复是怎么合并的
select * from table1
查询结果:

看看这样的一个简单的表我们是怎样合并相同的列的
第一步:当然是查看表的XML文件看看表是怎样组成的
select * from table1 for XML path;
查询的结果:
<row>
<uid>1</uid>
<rname>管理员</rname>
</row>
<row>
<uid>1</uid>
<rname>店主</rname>
</row>
<row>
<uid>1</uid>
<rname>买家</rname>
</row>
<row>
<uid>2</uid>
<rname>店主</rname>
</row>
<row>
<uid>2</uid>
<rname>店主</rname>
</row>
根据查询的结果我们不难看出表的组成的简单结构,可能是数据库自己定义好的也可能是我们在查询的时候自动生成的,不管是定义好的还是自己生成的我们先看看是否可以改变表的组成结构如果可以的话我们是不是就可以改变我们想要的结构呢?
第二步:改变表的组成结构
select * from table1 for XML path;
还是这句语句既然可以查询表的XML文件组成那是否可以改变表的XML文件的组成呢。试试就知道了(程序就是你想的再多不如你敲几行代码一试)
select * from table1 for XML path('a');
我们这样写语句看看我们的表的XML文件的组成变成了什么样:
<a>
<uid>1</uid>
<rname>管理员</rname>
</a>
<a>
<uid>1</uid>
<rname>店主</rname>
</a>
<a>
<uid>1</uid>
<rname>买家</rname>
</a>
<a>
<uid>2</uid>
<rname>店主</rname>
</a>
<a>
<uid>2</uid>
<rname>店主</rname>
</a>
比较两次的查询结果看看我们的表的XML文件发生了什么变化:
select * from table1 for XML path; XML文件:
<row>
<uid>1</uid>
<rname>管理员</rname>
</row> select * from table1 for XML path('a'); XML文件的组成:
<a>
<uid>1</uid>
<rname>管理员</rname>
</a>
可以产出<row>标签变成了<a>,那么我们把path('a')中的a去掉会变成什么样:
查询语句:
select * from table1 for XML path('');
查询结果:
<uid>1</uid>
<rname>管理员</rname>
<uid>1</uid>
<rname>店主</rname>
<uid>1</uid>
<rname>买家</rname>
<uid>2</uid>
<rname>店主</rname>
<uid>2</uid>
<rname>店主</rname>
比较两次的查询结果:
select * from table1 for XML path('a');
查询结果:
<a>
<uid>1</uid>
<rname>管理员</rname>
</a>
select * from table1 for XML path('');
查询结果:
<uid>1</uid>
<rname>管理员</rname>
可以看出<a>去掉了,我们想要的是什么是用户的角色那我们就要角色看看:
第三步:去掉多余的行
select rname from table1 for XML path('');
查询的结果:
<rname>管理员</rname>
<rname>店主</rname>
<rname>买家</rname>
<rname>店主</rname>
<rname>店主</rname>
当然这仍然不是我们想要的结果我们想要的里面的数据,所以我们需要去掉<rname>标签:
第四步:去掉不要的标签:
select rname+',' from table1 for XML path('');
查询的结果:
管理员,店主,买家,店主,店主,
这就是我们想要的结果了,结果是拿到了但是我们想要的是什么效果啊,先看看我们们想要的表是什么样的

这是我们想要的表,但是怎么组成呢?
再看看我们原来的表:

想想看我们应该把这张表变形:
uid是多行的那我们就先不看rname这一列,我们先进行分组:
第五步:分组
根据uId进行分组
select uid from table1 group by uid
结果:

好,最重要的一步来了:
我们怎么把管理员,店主,买家,放在对应uid为1的一行,怎么把店主,店主,放在对应的uid为2的一行后面
第六步:合并:
也就是在这个表的后面添加一列。这样就简单了
select uid,(这一列就是rname)from table1 t group by uid;
那我们就增加一列:
上面我们的查询时查询所有的列现在我们加上条件:
select rname+',' from table1 t1 where t1.uid=1 for XML path('');
查询结果:
管理员,店主,买家,
这不就是我们想要的嘛,只要把条件改变一下就可以了嘛,现在我们进行合并也就是增加一列。
select uid,(这一列就是rname)from table1 t group by uid;
增加rname这一列:
select uid,(select rname+',' from table1 t1 where t1.uid=t.uid for XML path('')) as rname from table1 t group by uid;
我们看看这个语句的查询结果是什么?
select uid,(select rname+',' from table1 t1 where t1.uid=t.uid for XML path('')) as rolenames from table1 t group by uid;
结果:

这就是我们想要的结果了。
好了简单表的组成会了我们来点复杂的
继续完成我们刚开始提出的问题:
合成这张表试试看
查询语句:
select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID

我们该怎么合并这张表呢。仔细想想看其实道理是一样的我们直接把这张表当让是table1表,在往刚刚的sql语句一套不就行了
看看刚才的sql语句:
select uid,(select rname+',' from table1 t1 where t1.uid=t.uid for XML path('')) as rolenames from table1 t group by uid;
看看哪里用到了table1我们改变一下就行了
select uid,(select rname+',' from (table1表) t1 where t1.uid=t.uid for XML path('')) as rolenames from (table1表) t group by uid;
再根据我们的表看一看也就是改变一下查询的列的问题:
我们改变一下
select USERID,(select t.ROLE_NAME+',' from (table1表))t where t.USERID=t1.USERID for XML path('')) as RoleName from(table1表)t1 group by USERID,TrueName,USERNAME
好了把我们的“table1表”放进去,执行一下看看什么结果
select USERID,(select t.ROLE_NAME+',' from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t where t.USERID=t1.USERID for XML path('')) as RoleName from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t1 group by USERID
查询结果:

可是跟上面的表比较一下我们的表少了几列所以我们要把少的几列加上:
select USERID,TrueName,USERNAME,(select t.ROLE_NAME+',' from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t where t.USERID=t1.USERID for XML path('')) as RoleName from
(select r.ROLE_NAME,u.USERID,u.USERNAME,u.TrueName from BASE_USERINFOR u
left join BASE_USERROLE ur on u.USERID=ur.USER_ID
left join BASE_ROLEINFOR r on r.ROLE_ID=ur.ROLE_ID) t1 group by USERID,TrueName,USERNAME
看看查询的结果是不是我们想要的

在这里一定要注意一下group by 后面的语句,虽然我们写那么多的分组条件就只是第一个条件及作用我们仍然要写因为只有这样我们在查询的时候才可以去查询想要的列。
所以当你想要的查询其他的列的时候你就需要在group by 后面加上此列。
sql多行多列重复的更多相关文章
- sql的行转列(PIVOT)与列转行(UNPIVOT) webapi 跨域问题 Dapper 链式查询 扩展 T4 代码生成 Demo (抽奖程序)
sql的行转列(PIVOT)与列转行(UNPIVOT) 在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比 ...
- Sql Server 行转列
--摘自百度 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (… ...
- sql的行转列(PIVOT)与列转行(UNPIVOT)
在做数据统计的时候,行转列,列转行是经常碰到的问题.case when方式太麻烦了,而且可扩展性不强,可以使用 PIVOT,UNPIVOT比较快速实现行转列,列转行,而且可扩展性强 一.行转列 1.测 ...
- 做图表统计你需要掌握SQL Server 行转列和列转行
说在前面 做一个数据统计和分析的项目,每天面对着各种数据,经过存储过程从源表计算汇总后需要写入中间结果表以提高数据使用效率,那么此时就需要用到行转列和列转行. 1.列转行 数据经过计算加工后会直接生成 ...
- SQL Server 行转列重温
转载自http://www.cnblogs.com/kerrycode/ 行转列,列转行是我们在开发过程中经常碰到的问题.行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER ...
- sql server 行转列(转载)
SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...
- sql server 行转列解决方案
主要应用case语句来解决行转列的问题 行转列问题主要分为两类 1)简单的行转列问题: 示例表: id sid course result 1 2005001 语文 ...
- sql server 行转列 Pivot UnPivot
SQL Server中行列转换 Pivot UnPivot 本文转自:张志涛 原文地址: http://www.cnblogs.com/zhangzt/archive/2010/07/29/17878 ...
- 【转载】SQL Server行转列,列转行
行转列,列转行是我们在开发过程中经常碰到的问题.行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 2005 新增的运算符PIVOT来实现.用传统的方法,比较好理解.层次清 ...
随机推荐
- mysql性能监控软件pmm
具体配置操作步骤:1.在vmware或者virtualbox上安装centos镜像,可以选择阿里巴巴的镜像,下载速度快 centos7 修改yum源为阿里源,某下网络下速度比较快 首先是到yum源设置 ...
- Ubuntu14.0使用gparted调整分区大小
不知道为什么,我总会碰到一些疑难杂症,别人的分区都是在同一个目录下,直接通过,不断调整同一目录下相邻分区之间的空间来达到调整目标分区大小的目的 但我的不一样,我的主要分区在扩展分区下,极其魔性,图片里 ...
- XV Open Cup named after E.V. Pankratiev. GP of America
A. Area of Effect 首先最优解中必有一个点在圆的边界上. 若半径就是$R$,则枚举一个点,然后把剩下的事件极角扫描即可,时间复杂度$O(m(n+m)\log(n+m))$. 否则圆必然 ...
- dagger2 依赖注入
前言: 当 mvp + dagger2 + rxjava 三者遇上,架构更加清晰,代码更加灵活,巧妙结合. 依赖注入:是为了解耦,达到高内聚低耦合的目的,保证代码的健壮性.灵活性和可维护性. publ ...
- Linux bash基础特性二
shell脚本的组成部分 shebang 各种命令组合 编程变量种类 本地变量: 仅仅在当前的shell生效 环境变量: 在当前和子shell生效 局部变量: shell进程某代码片段 位置变量: $ ...
- Java当中的IO一
1.IO操作的目标 什么是IO操作的目标? 输入: 从数据源当中读取数据 输出: 将数据写入到数据目的地当中 有数据进入到程序当中,这个过程就可以被叫做输入 流:即在数据源与程序之间建立的传输通道 2 ...
- centos7下部署nginx与php
背景介绍 相信读者在看这篇文章之前已经fastcgi,php-fpm有所了解.大概来讲php语言需要fastcgi程序,即php解释器解释,而php解释器需要php-fpm管理器进行调度. 以下对CG ...
- I Think I Need a Houseboat POJ - 1005
I Think I Need a Houseboat POJ - 1005 解题思路:水题 #include <iostream> #include <cstdio> #inc ...
- SyntaxError: invalid character in identifier(Python)
在写博客时直接将博客上的代码复制运行后发现错误SyntaxError: invalid character in identifier,我以为是l(小L)写成了1,改了还是不行. 上网查了下,发现原来 ...
- Vs Code 中文包设置
首先打开Vs Code 然后点击扩展 下载中文包 安装中文包 在没打开任何文件的时候我们可以看到一些提示 这个时候使用快捷键 Ctrl + Shift + P (显示所有命令),然后选择" ...